# NovaLoca Scraper — UK Commercial Property Listings (`studio-amba/novaloca-scraper`) Actor

Get UK commercial property listings from NovaLoca.com: offices, industrial, retail, land and leisure, for sale or to let. Prices with their exact unit (per annum, per month, per sq ft), floor sizes, locations, agents and images. No login or cookies required.

- **URL**: https://apify.com/studio-amba/novaloca-scraper.md
- **Developed by:** [Studio Amba](https://apify.com/studio-amba) (community)
- **Categories:** Real estate
- **Features:** Limited permissions
- **Stats:** 1 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 1,000 result scrapeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## NovaLoca Scraper — UK Commercial Property Listings

Get commercial property listings from [NovaLoca.com](https://www.novaloca.com), one of the UK's main commercial property portals: offices, industrial units and warehouses, retail premises, commercial land and leisure property, for sale or to let. After EG Propertylink closed in early 2026, NovaLoca picked up much of its market — the portal carries roughly 26,000 live listings across the UK.

Search by any UK town, city, region or postcode, filter by property segment and tenure, and get structured JSON with prices, floor sizes, locations, agent names and photos. No login or cookies required.

### Why use it

- **Market research** — track asking rents and sale prices per segment and region.
- **Deal sourcing** — investors and occupiers monitoring new stock in a target area, sorted by date added.
- **Agency intelligence** — see which agents list what, where, and at what price point.
- **Lead generation** — every listing carries the marketing agency's name.
- **Portfolio benchmarking** — compare your own asking prices against the local market.

UK commercial listings quote prices in several different units (per annum, per month, per sq ft). This actor never converts or guesses: you get the numeric price plus the exact unit string the site displays, so £12.50 per sq ft and £12,500 per annum stay distinguishable.

### Input options

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `searchQuery` | string | — | UK town, city, region or postcode (e.g. `Manchester`, `Bedfordshire`, `M1 1AD`). The site requires a location: when left empty the actor searches around London. Results are distance-ordered and reach well beyond the town itself. |
| `listingType` | string | `all` | `all`, `sale`, or `rent`. Properties offered as "for sale or to let" appear under both filters. |
| `propertyType` | string | `all` | `all`, `offices`, `industrial`, `retail`, `land`, or `leisure`. |
| `sort` | string | `distance` | `distance` (site default) or `date-added` (newest first). |
| `maxResults` | integer | `100` | Hard cap on returned listings. The whole portal holds ~26,000. |
| `proxyConfiguration` | object | UK residential | NovaLoca sits behind the Azure Front Door WAF, which answers plain requests with a JavaScript challenge. The actor solves it in a headless browser on a UK residential exit and retries on a fresh exit when a page is refused. |

#### Example input

```json
{
    "searchQuery": "Manchester",
    "propertyType": "offices",
    "listingType": "rent",
    "maxResults": 100
}
```

### Output fields

| Field | Type | Example | Description |
|-------|------|---------|-------------|
| `id` | string | `"293794"` | NovaLoca internal property ID |
| `title` | string | `"Manchester Road"` | Street or building name |
| `segment` | string | `"Offices"` | Segment label as shown on the site |
| `listingType` | string | `"rent"` | `sale`, `rent`, or `sale-or-rent`, from the listing URL |
| `saleTypeRaw` | string | `"To Let"` | Site's own tenure label on the primary price |
| `price` | number | null | `280` | Primary quoted price in GBP; `null` when price-on-application |
| `currency` | string | `"GBP"` | Always GBP |
| `priceUnit` | string | null | `"per month"` | Exact unit string the site quotes (`per annum`, `per month`, `per sq ft`); `null` for sale totals |
| `priceQuotes` | array | | Every price block on the card — one per tenure for "for sale or to let" listings |
| `sizeRaw` | string | null | `"50 to 5,000 Sq Ft"` | Size exactly as listed |
| `surfaceMin` | number | null | `50` | Lower bound of the size range |
| `surfaceMax` | number | null | `5000` | Upper bound of the size range |
| `surfaceUnit` | string | null | `"sq ft"` | Unit of the listed size |
| `city` | string | null | `"Manchester"` | Town from the listing URL |
| `distanceMiles` | number | null | `0` | Distance from the searched location |
| `agencyName` | string | null | `"Citrus Commercial Circle"` | Marketing agent |
| `description` | string | null | | Description snippet (truncated by the site) |
| `imageUrl` | string | null | | Primary listing photo |
| `url` | string | | Canonical listing page URL |
| `source` | string | `"novaloca.com"` | |
| `scrapedAt` | string | | ISO 8601 timestamp |

#### Example output

```json
{
    "id": "293794",
    "title": "Manchester Road",
    "segment": "Offices",
    "listingType": "rent",
    "saleTypeRaw": "To Let",
    "price": 280,
    "currency": "GBP",
    "priceUnit": "per month",
    "priceQuotes": [
        { "saleType": "To Let", "price": 280, "priceUnit": "per month" }
    ],
    "sizeRaw": null,
    "surfaceMin": null,
    "surfaceMax": null,
    "surfaceUnit": null,
    "city": "Manchester",
    "distanceMiles": 0,
    "agencyName": "Citrus Commercial Circle",
    "description": "A range of flexible commercial suites now available within Atrium House...",
    "imageUrl": "https://cdn.novaloca.com/imgs/xl_293794_639095345564222441.jpg",
    "url": "https://www.novaloca.com/office-space/to-let/manchester/manchester-road/293794",
    "source": "novaloca.com",
    "scrapedAt": "2026-08-18T10:30:00.000Z"
}
```

### How to scrape NovaLoca data

1. Open the actor on Apify and press **Try for free**.
2. Enter a UK location in **Location** (e.g. `Manchester`, `Leeds`, `Bristol`).
3. Pick a **Property Type** (offices, industrial, retail, land, leisure) and a **Listing Type** (for sale, to let, or both).
4. Set **Max Results** and press **Start**.
5. When the run finishes, download the dataset from the **Output** tab as JSON, CSV or Excel.

You can also run it via the Apify API or schedule it to track new listings — set `sort` to `date-added` and a schedule, and each run returns the newest stock first.

### Cost estimate

The actor opens one headless browser to pass the site's WAF challenge (about 5 seconds), then fetches 200 listings per page request, so nearly all usage cost is the per-result charge. It needs at least 1 GB of memory; a lower memory setting is raised to 1 GB automatically. Expect roughly **$0.002 per listing** plus a small run start fee — about $0.20 for a 100-listing run, or roughly 500 listings per $1. A run's usage cost only settles once it reports SUCCEEDED; a cost read mid-run understates the final figure.

### Limitations

- A location NovaLoca does not recognise (for example a misspelling) returns 0 listings. The run still ends SUCCEEDED and its status message says the location was not found.
- Listing descriptions are the search-card snippets, truncated by the site. Full descriptions, postcodes and the agent's phone number live on the detail pages, which this actor does not visit.
- The site requires a location and orders results by distance from it, so a search is effectively regional: nearby towns appear in the results with their `distanceMiles` value.
- Prices marked "price on application" come back as `null` — the site publishes no number for them.
- Some listings do not specify a floor size; `sizeRaw` and the surface fields are `null` for those.

# Actor input Schema

## `searchQuery` (type: `string`):

UK town, city, region or postcode to search around (e.g. 'Manchester', 'Leeds', 'Bedfordshire', 'M1 1AD'). Results are distance-ordered from this point and reach well beyond the town itself. The site requires a location — when this is left empty the actor searches around London.

## `listingType` (type: `string`):

For sale, to let, or both. Properties offered as 'for sale or to let' appear in both filters.

## `propertyType` (type: `string`):

Commercial property segment. 'All types' returns every segment on the portal.

## `sort` (type: `string`):

How the portal orders results: by distance from the searched location (site default) or by date added (newest first).

## `maxResults` (type: `integer`):

Maximum number of listings to return. Hard cap for the run — the whole portal holds roughly 26,000 listings.

## `proxyConfiguration` (type: `object`):

Proxy settings. NovaLoca sits behind the Azure Front Door WAF, which answers plain requests with a JavaScript challenge; the actor solves it in a headless browser. UK residential proxy is the reliable default.

## Actor input object example

```json
{
  "searchQuery": "Manchester",
  "listingType": "all",
  "propertyType": "all",
  "sort": "distance",
  "maxResults": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "GB"
  }
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "searchQuery": "Manchester",
    "maxResults": 20,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "GB"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("studio-amba/novaloca-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "searchQuery": "Manchester",
    "maxResults": 20,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "GB",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("studio-amba/novaloca-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchQuery": "Manchester",
  "maxResults": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "GB"
  }
}' |
apify call studio-amba/novaloca-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,studio-amba/novaloca-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/yeHa0wg4Y5h87A7Yq/builds/xpsj0S5EPICWWgAuK/openapi.json
