# 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
- **Stats:** 2 total users, 1 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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# 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 blocklists individual IPs. UK residential proxy is the reliable default; the automatic pool also worked in testing. |

#### 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 fetches 200 listings per page request, so nearly all usage cost is the per-result charge. 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

- 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 blocklists individual IPs (verified in recon, docs/site-recon/novaloca.md) — UK residential proxy is the reliable default. The free automatic pool also passed recon if you want cheaper runs.

## 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/gMROXgwB5HqUfdQKd/openapi.json
