# Jitty Scraper - UK Property Listings & AI Search (`abotapi/jitty-uk-scraper`) Actor

Scrape residential property listings from Jitty.com across the UK. Search with 20+ property filters, including AI vision search, and extract clean structured data for homes, prices, locations, features and more.

- **URL**: https://apify.com/abotapi/jitty-uk-scraper.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Categories:** Real estate, AI, Automation
- **Features:** Limited permissions
- **Stats:** 3 total users, 0 monthly users, 96.7% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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

## Jitty UK Scraper: Property Listings, Prices, Coordinates & EPC Data

Jitty UK Scraper turns jitty.com into structured UK for-sale property data. Search by location and more than 15 filters (property type, price, bedrooms, tenure, condition, exterior style, floor area, interior features, green tech, date added), add an AI vision search term such as "sea views" or "cottage" on top of any filter, or paste jitty.com search-result URLs directly. Every listing carries price, bedrooms, price per square foot and up to 10 photos from the search results, and can add tenure, EPC ratings, floor area, estate agent, coordinates and nearby transport stations from the property's own detail page. Export to JSON, CSV or Excel, or pull results straight into your app through the API.

### Why This Scraper?

- **Two ways to search, plus AI vision search.** Build a search from more than 15 filters (location, price, bedrooms, tenure, condition, exterior style, floor area, interior features, green tech, date added), or paste jitty.com search-result URLs directly. Add an AI vision search term like "sea views" or "cottage" on top of any other filter.
- **Full-detail enrichment, on demand.** Turn on Include full details to add coordinates, floor area, tenure, EPC ratings, council tax band, estate agent, the complete feature list and nearby transport stations from each property's own detail page, or turn it off for card-level fields only.
- **Resume one interrupted crawl.** Paste a previous run or dataset ID and the next run skips everything already collected, so a large crawl can continue without paying twice.
- **Recurring monitoring built in.** Turn on Incremental mode to get only NEW, UPDATED and REAPPEARED properties on every scheduled run, with unchanged properties suppressed and not billed.
- **A cap that matches what you pay for.** Max properties counts rows actually returned, not scanned, so a page of mostly-unchanged listings still backfills from later pages toward your cap.
- **Built for schedules.** A run that could not read a single result page fails loudly instead of returning an empty dataset, so "no properties found" is never confused with "the site refused every request".
- **Send results into your apps.** Optionally pipe scraped properties into Notion, Linear, Airtable or Apify through MCP connectors, right after the scrape.

### Use Cases

- **Property investors and analysts:** compare price per square foot, tenure and EPC ratings across a location to find undervalued or high-yield properties.
- **Home buyers and renovators:** filter by condition, exterior style and interior features such as fireplaces or high ceilings to shortlist period and character properties.
- **Portfolio and market monitors:** schedule Incremental mode against a saved search to receive only new listings and price changes, without re-downloading everything each time.
- **Real estate and comparison sites:** build a listings feed with photos, agent details and nearby transport links for a location page.
- **Market researchers and data teams:** build a historical dataset of prices, features and availability for a city or region.

### Data You Get

> Sample shape: values are illustrative placeholders, not from a live record.

| Field | Example |
| --- | --- |
| `id` | `"SampleSlugID1234567"` |
| `title` | `"Mill Lane, Sampleford"` |
| `address` | `"12 Mill Lane, Sampleford, Greater London"` |
| `price` / `price_numeric` | `"£450,000"` / `450000` |
| `currency` | `"GBP"` |
| `bedrooms` / `bathrooms` | `3` / `2` |
| `property_type` | `"Terraced"` |
| `property_type_detail` | `"End of Terrace"` |
| `price_per_sqft` | `"£512 /sqft"` |
| `area_sqft` | `880` |
| `ownership` | `"Freehold"` |
| `living_spaces` | `2` |
| `council_tax_band` | `"D"` |
| `epc_current_score` / `epc_current_rating` | `72` / `"C"` |
| `epc_potential_score` / `epc_potential_rating` | `88` / `"B"` |
| `lease_years_remaining` | `999` (leasehold only) |
| `estate_agent` | `"Sample Estates"` |
| `latitude` / `longitude` | `51.5010` / `-0.1246` |
| `location_source` | `"detail_page"` |
| `tags` | `["Fireplace", "Garden"]` |
| `features` | `["Fireplace", "Garden", "Patio", "High Ceilings"]` |
| `nearby_stations` | `[{"name": "Sampleford Park", "distance_miles": 0.4}]` |
| `images` | up to 10 photo URLs |
| `image_count` | `14` |
| `url` | `"https://jitty.com/properties/SampleSlugID1234567"` |

When Incremental mode is on, every returned record also carries `changeType` (`NEW`, `UPDATED`, `UNCHANGED`, `REAPPEARED` or `EXPIRED`), `changedFields` (populated only for `UPDATED`), `firstSeenAt` and `lastSeenAt`. See "Resume and recurring updates" below.

### How to Use

1. Pick a **mode**: `search` (build a search from filters, or from an AI vision search term) or `url` (paste jitty.com search-result URLs directly).
2. In search mode, set **location** and any filters you need: property type, price, bedrooms, ownership, condition, exterior style, area, interior features, green tech, date added.
3. Turn **Include full details** on or off, then set **Max properties** and **Max pages** to control run size and cost.
4. Click **Start**. Download the dataset as JSON, CSV or Excel, or read it through the API.

**Flats for sale in Greenwich, under £500k:**

```json
{
  "mode": "search",
  "location": "greenwich",
  "property_type": "flat",
  "max_price": 500000,
  "max_properties": 20
}
```

**Period properties with fireplaces in Bath:**

```json
{
  "mode": "search",
  "location": "bath",
  "exterior_style": "period",
  "interior_features": ["fireplace"],
  "max_properties": 20
}
```

**AI vision search for coastal-looking properties:**

```json
{
  "mode": "search",
  "look_for": "sea_views",
  "property_type": "detached",
  "max_properties": 20
}
```

**Paste a search-result URL directly:**

```json
{
  "mode": "url",
  "urls": ["https://jitty.com/for-sale/manchester/terraced-property-type"]
}
```

#### URL mode: accepted URL shapes

Every shape below is checked live. `http://`, `www.` and trailing-slash forms are normalised to `https://jitty.com/...`, duplicates are dropped, and the query (`?page=N`, `?sort=...`) is kept.

| Shape | Example | Notes |
|---|---|---|
| All-UK listing | `https://jitty.com/for-sale` | |
| City or location | `https://jitty.com/for-sale/bath` | `london` works the same way |
| Region + property type | `https://jitty.com/for-sale/east-london/flat-property-type` | |
| Location + bedrooms + type | `https://jitty.com/for-sale/london/at-least-2-bedrooms/flat-property-type` | |
| Location + price | `https://jitty.com/for-sale/london/price-up-to-200000-gbp` | |
| Location + area type | `https://jitty.com/for-sale/london/rural-area-type` | |
| Start at page N | `https://jitty.com/for-sale/london/flat-property-type?page=2` | Pages before N are not read, so `emitExpired` is skipped for it |
| Sorted | `https://jitty.com/for-sale/london/flat-property-type?sort=price_asc` | Passed to the site as given; the site's own ordering is returned and not verified by the actor |
| Commute + look-for | `https://jitty.com/for-sale/paddington-station/travel-by-public-transport/travel-for-60-minutes/look-for-sauna` | |
| Map view | `https://jitty.com/for-sale/map/london/flat-property-type` | A map page lists no cards, so the matching list page is scraped and a warning is logged |
| Single property | `https://jitty.com/properties/lrlS0BMHI5MEzJRYM9n9` | One record from the property page, with its detail fields. Billed as one property plus one `detail-enrichment`, even when Include full details is off |

A location the site does not recognise is reported as an error ("No match on jitty.com") instead of silently returning the whole country; if every search is unrecognised, the run fails with that message.

**Default behaviour:** if you switch to `url` mode and leave the URLs field untouched, the actor now scrapes the built-in example URLs, one per shape above (it used to stop with "No URLs provided"). Max properties is the overall cap across all URLs, so a small cap is filled by the first examples. Charges follow the usual rule: only delivered rows are billed.

#### Run it from your code

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/jitty-uk-scraper").call(run_input={"mode": "search", "location": "bath", "property_type": "terraced"})
for prop in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(prop["title"], prop["price"])
```

JavaScript:

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

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/jitty-uk-scraper').call({ mode: 'search', location: 'bath', property_type: 'terraced' });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the **Integrations** tab.

#### How Max properties and Max pages shape a run

Search results page through automatically, about 23 listings per page. **Max pages** stops the walk after that many pages (leave it empty or `0` to go as deep as needed, bounded by Max properties instead). **Max properties** counts properties actually returned this run, not scanned: if Incremental mode suppresses some (unchanged) properties from a page, the run backfills from later pages up to your cap rather than stopping early just because a page was mostly unchanged.

With Incremental mode and a non-zero Max properties, each page is only checked up to the quota still open when that page is read; when unchanged properties free up quota, the run moves on to the next page instead of going back for the rest of the current one, so some properties on that page are not checked in this run. For scheduled monitoring that should see every property in the search, set Max properties to `0` and limit run size with Max pages or a narrower search instead.

#### Resume and recurring updates

There are two different things here; pick the one that matches what you are doing:

| Situation | Use |
| --- | --- |
| A crawl stopped and should continue | `resumeFromRunId` |
| Run the same search on a schedule and receive only changes | `incrementalMode` |
| Keep separate recurring campaigns for similar searches | distinct `stateKey` values |
| Run a normal full snapshot | leave both off |

**Resume** (`resumeFromRunId`) continues one specific interrupted or previous large crawl: paste a run ID or dataset ID and this run skips properties already collected there, returning only the remaining new ones.

**Incremental mode** (`incrementalMode`) is for a schedule (daily or weekly, for example): the actor remembers the previous run of the *same* search by itself, so no run ID needs pasting. The first run returns everything as `NEW`. Later runs return only `NEW`, `UPDATED` and `REAPPEARED` properties by default; duplicates and unchanged properties are suppressed and not charged. Turn on `emitUnchanged` or `emitExpired` only when you also want those rows returned (and billed for). `emitExpired` only fires once a run has fully scanned the search (not capped, not a resume, no blocked page); otherwise the previous state is kept as-is and a log line explains why. Use it with Max properties set to `0`: with a cap, a property left unchecked on a partly read page (see above) can be reported `EXPIRED` even though it is still listed, and then `REAPPEARED` on a later run. State is isolated automatically per location or URL and every filter (including the detail toggle, area type and the commute destination, mode and minutes), but **not** by `max_properties` or `max_pages`, which are scan-depth and output caps rather than part of the tracked search; set `stateKey` to name or deliberately share a monitoring campaign. The two mechanisms combine only to bootstrap a first Incremental mode run from an earlier plain crawl: once Incremental mode already has saved state for a search, adding `resumeFromRunId` on top of it is rejected, so the same properties are never double-counted. `emitExpired` is also skipped when a pasted search URL starts at `?page=2` or higher, because the earlier pages were never read. `ignoreFieldsForChanges` lets you exclude extra output fields (or a nested key such as `nearby_stations.distance`) from change detection; the fields are still returned, they just never make a property `UPDATED`. The rotating AI tag pills (`tags`) are always excluded. Changing the list does not reset your baseline and causes no one-time wave of `UPDATED` rows.

The small "tags" pill list shown on each search card is resampled by jitty.com on every render, unlike the full `features` list from the detail page, which stays stable. `tags` is excluded from Incremental mode's change detection for this reason: a property is never reported `UPDATED` just because its `tags` sample looks different between two runs. `price`, `features`, `images` and every other field are real signals and are always compared, including a price reduction, which is exactly what a recurring monitoring run is for.

### Send results into your apps (MCP connectors)

Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step **after** the scrape: the Apify dataset is never changed.

**What gets written to the connector:** a condensed, human-readable **summary** of each record, not the full JSON. Each item becomes one entry with a **title** and its key fields flattened to plain text. The **complete record always stays in the Apify dataset**.

1. Authorize a connector once under **Apify → Settings → Integrations** (Notion, Linear, Airtable, or Apify).
2. Select it in the **"Pipe results into your apps"** input field. (If the picker is empty, you haven't authorized a connector yet.)
3. For **Notion**, also set `notionParentPageUrl` to the page where items should be created.

The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.

### Input Parameters

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `mode` | string | `search` | `search` (build a URL from filters) or `url` (use provided URLs). |
| `location` | string | `london` | Location to search (for example "london", "bath", "greenwich", "manchester"). Leave empty for all UK. |
| `radius_miles` | integer | (none) | Expand the search to include nearby areas within this many miles of the location. |
| `area_type` | string | (none) | `rural` restricts results to rural properties in the location. |
| `commute_station` | string | (none) | Find homes within a travel time of a station or place; replaces `location` and `radius_miles`. |
| `travel_mode` | string | `public-transport` | `public-transport`, `walking` or `cycling`. |
| `travel_minutes` | integer | (none) | 15, 30, 45 or 60. Required for a commute search; any other value (or a missing one) stops the run with an error instead of searching the default location. |
| `look_for` | string | (none) | AI vision search by visual features (for example "cottage", "sea_views", "warehouse_conversion"). Can be combined with location and other filters. |
| `property_type` | string | (none) | `flat`, `detached`, `semi-detached`, `terraced`, `bungalow`, `maisonette`, `land`, `boat`, `mobile-home`, `parking`. |
| `bedrooms` | integer | (none) | Minimum number of bedrooms (0 = Studio+). |
| `max_bedrooms` | integer | (none) | Maximum number of bedrooms. |
| `min_bathrooms` | integer | (none) | Minimum number of bathrooms. |
| `min_price` | integer | (none) | Minimum price in GBP (use with `max_price` for a range). |
| `max_price` | integer | (none) | Maximum price in GBP. |
| `ownership` | string | (none) | `freehold`, `leasehold`, `shared-ownership`, `share-of-freehold`. |
| `condition` | string | (none) | `good`, `renovation-potential`, `renovation-needed`, `derelict`. |
| `exterior_style` | string | (none) | `period`, `contemporary`, `early-modern`, `late-modern`. |
| `date_added` | string | (none) | `24h`, `3d`, `1w`, `1m`. |
| `min_area_sqft` | integer | (none) | Minimum floor area in square feet. |
| `max_area_sqft` | integer | (none) | Maximum floor area in square feet. |
| `outside_space` | string | (none) | `garden`, `large-garden`, `balcony`, `roof-terrace`, `communal-garden`, `patio`. |
| `interior_features` | array | (none) | `fireplace`, `exposed-brickwork`, `high-ceilings`, `sash-windows`, `wooden-beams`, `vaulted-ceilings`, `open-plan-kitchen`, `kitchen-island`, `breakfast-bar`. Multiple values combine. |
| `green_tech` | string | (none) | `solar-panels`, `ev-charger`, `heat-pump`, `underfloor-heating`. |
| `urls` | array | built-in examples, one per URL shape | jitty.com search-result or property URLs to scrape (`url` mode only). |
| `include_details` | boolean | `true` | Add coordinates, floor area, tenure, EPC, council tax, estate agent, features and full address from each property's detail page. Turn off for a lighter run with card-level fields only. |
| `max_properties` | integer | `10` | Maximum number of properties to return (`0` = unlimited). |
| `max_pages` | integer | (none) | Maximum search result pages to fetch. Leave empty (or `0`) to go as deep as needed, bounded by Max properties. |
| `resumeFromRunId` | string | (none) | Continue one interrupted crawl: paste a previous run or dataset ID and this run skips properties already collected. For recurring monitoring of the same search instead, use Incremental mode. |
| `incrementalMode` | boolean | `false` | Remembers the previous run of this same search itself and classifies every property as NEW, UPDATED, UNCHANGED, REAPPEARED or EXPIRED. Intended for scheduled, recurring runs against an unchanged search. |
| `stateKey` | string | (none) | Manual label for the Incremental mode baseline. Leave empty to auto-derive one from the mode, location or URLs and every filter. Set this to deliberately share one baseline across otherwise-different filter setups. |
| `emitUnchanged` | boolean | `false` | Incremental mode only. Also return (and bill for) properties unchanged since the last run, marked `UNCHANGED`. |
| `emitExpired` | boolean | `false` | Incremental mode only. Also return (and bill for) properties from a previous run no longer found, marked `EXPIRED`, once a run has fully scanned the search. |
| `ignoreFieldsForChanges` | array | `[]` | Incremental mode only. Extra field names (or dotted nested paths such as `nearby_stations.distance`) to exclude from `UPDATED` change detection, on top of the built-in exclusion of `tags`. Excluded fields are still returned. |
| `proxy` | object | Apify residential, GB | Proxy configuration. |
| `mcpConnectors` | array | (none) | Optional: send a summary of each record to apps you authorized under Integrations. |
| `notionParentPageUrl` | string | (none) | Notion connector only: page under which item pages are created. |
| `maxNotifyListings` | integer | `50` | Cap on items written to each connector per run. Does not affect the dataset. |

### Output Example

> Sample shape: values are illustrative placeholders, not from a live record.

```json
{
  "id": "SampleSlugID1234567",
  "title": "Mill Lane, Sampleford",
  "address": "12 Mill Lane, Sampleford, Greater London",
  "price": "£450,000",
  "price_numeric": 450000,
  "currency": "GBP",
  "bedrooms": 3,
  "bathrooms": 2,
  "property_type": "Terraced",
  "property_type_detail": "End of Terrace",
  "price_per_sqft": "£512 /sqft",
  "area_sqft": 880,
  "ownership": "Freehold",
  "living_spaces": 2,
  "council_tax_band": "D",
  "epc_current_score": 72,
  "epc_current_rating": "C",
  "epc_potential_score": 88,
  "epc_potential_rating": "B",
  "estate_agent": "Sample Estates",
  "latitude": 51.501,
  "longitude": -0.1246,
  "location_source": "detail_page",
  "tags": ["Fireplace", "Garden"],
  "features": ["Fireplace", "Garden", "Patio", "High Ceilings"],
  "nearby_stations": [{ "name": "Sampleford Park", "distance_miles": 0.4 }],
  "images": ["https://jitty-cdn.com/blobs/sample-image-01"],
  "image_count": 14,
  "url": "https://jitty.com/properties/SampleSlugID1234567"
}
```

### Plan Requirement

jitty.com protects its pages with an access check. Datacenter and direct connections are refused with a "Just a moment..." page, so residential access is required: the default connection (Apify residential proxy, United Kingdom) is what makes the actor work, and it needs an Apify plan that includes residential proxies (or your own proxy URLs). Refusals can be intermittent per exit, so the actor retries across exits and, if the default connection is unavailable, continues on a backup connection.

What you will see in the run log and status:

- **Warning, default connection unavailable** (logged as four consecutive warning lines):
  - "The selected connection is unavailable to this run."
  - "Apify free plans do not include residential proxies."
  - "Continuing on a backup connection; some pages may still be unavailable."
  - "For residential access, upgrade at https://apify.com/pricing or supply your own proxy URLs."
- **Info, backup connection carried data:** "Served over the backup connection (the default connection was unavailable)."
- **Failure, proxy refused for the account:** "The proxy connection was refused for this account, so no page could be read. Your Apify plan does not include proxy access; a paid plan is required: https://apify.com/pricing. If you entered your own proxy URLs, check that their credentials are valid."
- **Failure, no residential and backup could not load pages:** "No results: residential proxies are unavailable on this run (Apify free plans do not include them), and the backup connection could not load the requested Jitty pages. Upgrade at https://apify.com/pricing or supply your own proxy URLs, then try again."
- **Failure, no page loaded:** "Could not load any results page (the requests failed), so nothing was collected. This is a connection problem, not an empty search. Please try again later."

`look-for-...` keyword pages load their results as lazy cards; the actor fetches each card, so they return the same fields as other search pages.

### FAQ

#### How much does it cost?

Billing is per delivered result: one `apify-default-dataset-item` event for each property returned to the dataset, plus one `detail-enrichment` event for each property whose detail page was actually fetched (coordinates, EPC, tenure, agent and the rest of Include full details). A pasted property page URL (`/properties/<id>`) is billed the same way, as one property plus one `detail-enrichment`, whatever Include full details is set to, because the record is built from that detail page. Properties suppressed in Incremental mode (unchanged or duplicate), skipped or failed are not billed. The **Pricing** tab shows the current rates. Use **Max properties** to cap the cost of any run.

#### What is the Changes view?

With Incremental mode on, the dataset has a **Changes (incremental)** view that shows each property's `changeType`, `changedFields`, `firstSeenAt` and `lastSeenAt`. Use `ignoreFieldsForChanges` to keep noisy fields from triggering `UPDATED`.

#### Is it legal to scrape jitty.com?

This actor collects only publicly available property listing data. You are responsible for how you use it: follow jitty.com's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Listing photos and estate agent details may be subject to third-party rights.

#### Can I get only new or changed properties on a schedule?

Yes. Schedule the actor from the **Schedules** tab with the same search input and turn on **Incremental mode**. Each run then returns only `NEW`, `UPDATED` and `REAPPEARED` properties, and unchanged ones are not billed unless **Emit unchanged properties** is on. Set **Max properties** to `0` so every scheduled run checks the whole search (see "How Max properties and Max pages shape a run" above).

#### What is the difference between Resume and Incremental mode?

**Resume** (`resumeFromRunId`) continues ONE specific interrupted crawl: paste a previous run or dataset ID and this run skips everything it already collected. **Incremental mode** is for a recurring schedule over the SAME search: the actor remembers the previous run itself, so no ID needs pasting. The two combine only to bootstrap a first Incremental mode run from an earlier plain crawl; once Incremental mode has saved state for a search, adding Resume on top of it is rejected, so the two mechanisms never double-count the same properties.

#### Why did my run fail instead of returning an empty dataset?

If the site refused every request for every result page, the run stops with a clear message so "no properties found" is never confused with "nothing could be read". Run it again in a few minutes. If the run's time limit was reached before any page could be read, the message says so instead. A run that read at least one page returns whatever it found, even if a later page could not be read.

#### Why do AI-labeled tags sometimes look unrelated to what actually changed?

The short "tags" pill list shown on each search card is resampled by jitty.com on every render, unlike the full feature list on the detail page, which stays stable. Because of that, `tags` is excluded from Incremental mode's change detection: a property whose `tags` sample looks different between two runs is not reported as `UPDATED` unless a real field, such as price or the full feature list, also changed.

#### Can I use it with AI agents or MCP?

Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.

### 🔗 Want more real estate data?

Pair this actor with these related scrapers from the same team:

<table>
<tr><td>🧩 <a href="https://apify.com/abotapi/zoopla-co-uk-scraper"><b>Zoopla Scraper</b></a><br>Scrape UK property from Zoopla: for sale, to rent and Land Registry sold prices. Search...</td><td>🏠 <a href="https://apify.com/abotapi/rightmove-scraper"><b>Rightmove</b></a><br>Fast, reliable Rightmove.co.uk scraper for sale, rent, and sold-price listings. Search by...</td></tr>
<tr><td>🏠 <a href="https://apify.com/abotapi/iproperty-com-my-scraper"><b>iProperty MY Scraper</b></a><br>Scrape property listings from iProperty.com.my for sale or rent: price, PSF, bedrooms...</td><td>🏠 <a href="https://apify.com/abotapi/onthemarket-scraper"><b>OnTheMarket Scraper</b></a><br>Scrape onthemarket.com for-sale, to-rent and new-homes listings with 85+ fields: price...</td></tr>
<tr><td>👗 <a href="https://apify.com/abotapi/next-uk-product-scraper"><b>Next.co.uk Scraper</b></a><br>Scrape Next.co.uk: keyword search, category and product-listing walks, full product...</td><td>🏠 <a href="https://apify.com/abotapi/propertyguru-sg-scraper"><b>PropertyGuru SG Scraper</b></a><br>Scrape PropertyGuru.com.sg sale and rental listings with 30+ structured fields, including...</td></tr>
</table>

👉 [Browse all abotapi scrapers](https://apify.com/abotapi)

### 💬 Support

- 🐞 **Found a bug or a missing field?** Open a ticket on the [Issues tab](https://apify.com/abotapi/jitty-uk-scraper/issues/open). We usually reply within hours.
- 🛠️ **Need another site, extra fields or a private build?** Email <contact@abotapi.com>.
- ⭐ **Enjoying it?** A quick review on the actor page helps other users find it.

# Actor input Schema

## `mode` (type: `string`):

Scraping mode: 'search' builds URL from filters, 'url' uses provided URLs directly

## `location` (type: `string`):

Location to search (e.g. 'london', 'bath', 'greenwich', 'manchester'). Leave empty for all UK.

## `radius_miles` (type: `integer`):

Expand the search to include nearby areas within this many miles of the location.

## `area_type` (type: `string`):

Restrict to rural properties in the location. Only rural narrows results on the site.

## `commute_station` (type: `string`):

Find homes within a travel time of this station or place (for example paddington-station). Used together with Travel Minutes; replaces Location and Search Radius.

## `travel_mode` (type: `string`):

How you travel to the commute destination. Default public-transport.

## `travel_minutes` (type: `integer`):

Maximum travel time in minutes to the commute destination: 15, 30, 45 or 60. Required when Commute Destination is set; any other value stops the run with an error instead of searching the default location.

## `look_for` (type: `string`):

Search by visual features (e.g. 'cottage', 'sea_views', 'warehouse_conversion', 'barn_conversion', 'character_property'). Can be combined with location and other filters.

## `property_type` (type: `string`):

Filter by property type

## `bedrooms` (type: `integer`):

Minimum number of bedrooms (0=Studio+)

## `max_bedrooms` (type: `integer`):

Maximum number of bedrooms

## `min_bathrooms` (type: `integer`):

Minimum number of bathrooms

## `min_price` (type: `integer`):

Minimum price in British Pounds (use with max_price for range)

## `max_price` (type: `integer`):

Maximum price in British Pounds

## `ownership` (type: `string`):

Filter by ownership type

## `condition` (type: `string`):

Filter by property condition

## `exterior_style` (type: `string`):

Filter by exterior style

## `date_added` (type: `string`):

Filter by when listing was added

## `min_area_sqft` (type: `integer`):

Minimum floor area in square feet

## `max_area_sqft` (type: `integer`):

Maximum floor area in square feet

## `outside_space` (type: `string`):

Filter by outdoor area type

## `interior_features` (type: `array`):

Filter by interior features. Multiple features are combined.

## `green_tech` (type: `string`):

Filter by green technology

## `urls` (type: `array`):

jitty.com URLs to scrape (url mode only). Accepted shapes: all-UK listing, a location, location with filters (property type, bedrooms, price, area type), ?page=N and ?sort=, commute search with look-for, map views (read as the list page) and single property pages. http://, www. and trailing slashes are normalised. Leave the field untouched to scrape the built-in example of each shape.

## `include_details` (type: `boolean`):

Add coordinates, floor area, tenure, EPC, council tax, estate agent, features, and full address to each property. Turn off for a faster, lighter run with card-level fields only.

## `max_properties` (type: `integer`):

Maximum number of properties to scrape (0=unlimited)

## `max_pages` (type: `integer`):

Maximum search result pages to fetch. Leave empty (or 0) to go as deep as needed, bounded by Max Properties.

## `proxy` (type: `object`):

Proxy configuration. GB residential proxy recommended.

## `resumeFromRunId` (type: `string`):

Continue ONE interrupted crawl: paste a previous run or dataset ID and this run will skip properties it already collected. For recurring monitoring of the same search instead, use Incremental mode below (the two are mutually exclusive when Incremental mode has no saved state yet).

## `incrementalMode` (type: `boolean`):

Remembers the previous run of this SAME search itself (no need to paste a run ID) and classifies every property as NEW / UPDATED / UNCHANGED / REAPPEARED / EXPIRED. Intended for scheduled/recurring runs against an unchanged search. See 'Resume from run/dataset ID' above for continuing one interrupted crawl instead.

## `stateKey` (type: `string`):

Manual label for the Incremental mode baseline. Leave empty to auto-derive one from the mode, location/URLs and every filter (so two different searches never share state). Set this to deliberately share one baseline across otherwise-different filter setups.

## `emitUnchanged` (type: `boolean`):

Incremental mode only. When off (default), a property with no detected change since the last run is not returned or billed. Turn on to also return (and bill for) UNCHANGED rows.

## `emitExpired` (type: `boolean`):

Incremental mode only. When on, a property tracked in a previous run that no longer appears after a complete scan of this search is returned once with changeType EXPIRED (and billed like any other row). Skipped whenever this run did not reach a genuine end of results (a page cap, a blocked page, or Resume from run/dataset ID).

## `ignoreFieldsForChanges` (type: `array`):

Incremental mode only. Extra output field names to exclude from change detection, on top of the built-in exclusion of the rotating AI tag pills (tags). A field you list is still returned in every row but never makes a property UPDATED or appears in changedFields. A dotted name such as nearby_stations.distance ignores that key inside every list entry while the rest stays compared. Changing this list does not reset your baseline.

## `mcpConnectors` (type: `array`):

Optionally send the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize a connector once under Apify → Settings → Integrations, then select it here. The connector receives a condensed, human-readable summary per item (title + key fields), not the full JSON — the complete record stays in the dataset. Leave empty to skip. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com).

## `notionParentPageUrl` (type: `string`):

URL (or id) of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors.

## `maxNotifyListings` (type: `integer`):

Cap on items written to each connector per run. Does not affect the dataset.

## Actor input object example

```json
{
  "mode": "search",
  "location": "london",
  "urls": [
    "https://jitty.com/for-sale",
    "https://jitty.com/for-sale/bath",
    "https://jitty.com/for-sale/london",
    "https://jitty.com/for-sale/east-london/flat-property-type",
    "https://jitty.com/for-sale/london/at-least-2-bedrooms/flat-property-type",
    "https://jitty.com/for-sale/london/price-up-to-200000-gbp",
    "https://jitty.com/for-sale/london/rural-area-type",
    "https://jitty.com/for-sale/london/flat-property-type?page=2",
    "https://jitty.com/for-sale/london/flat-property-type?sort=price_asc",
    "https://jitty.com/for-sale/paddington-station/travel-by-public-transport/travel-for-60-minutes/look-for-sauna",
    "https://jitty.com/for-sale/london/flat-property-type/",
    "http://jitty.com/for-sale/bath",
    "https://jitty.com/for-sale/greenwich/look-for-waterfront",
    "https://jitty.com/for-sale/look-for-castle",
    "https://jitty.com/for-sale/london/within-5-miles/price-200000-to-500000-gbp/at-least-2-bedrooms",
    "https://jitty.com/for-sale/shoreditch/within-0.5-miles/flat-or-maisonette-property-type",
    "https://www.jitty.com/for-sale/greenwich",
    "https://jitty.com/for-sale/map/london/flat-property-type",
    "https://jitty.com/properties/lrlS0BMHI5MEzJRYM9n9"
  ],
  "include_details": true,
  "max_properties": 10,
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "GB"
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "ignoreFieldsForChanges": [],
  "maxNotifyListings": 50
}
```

# Actor output Schema

## `listings` (type: `string`):

Individual property listing records with price, features, coordinates, and detail page data.

## `metadata` (type: `string`):

Scraping run metadata including timing, counts, and configuration.

## `overview` (type: `string`):

Compact table: price, beds, baths, type, area, tenure, link.

## `map` (type: `string`):

Coordinates view for plotting listings.

## `details` (type: `string`):

Council tax, EPC, agent and feature detail.

## `changes` (type: `string`):

Incremental mode: changeType, changedFields, firstSeenAt, lastSeenAt per property.

# 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 = {
    "mode": "search",
    "location": "london",
    "urls": [
        "https://jitty.com/for-sale",
        "https://jitty.com/for-sale/bath",
        "https://jitty.com/for-sale/london",
        "https://jitty.com/for-sale/east-london/flat-property-type",
        "https://jitty.com/for-sale/london/at-least-2-bedrooms/flat-property-type",
        "https://jitty.com/for-sale/london/price-up-to-200000-gbp",
        "https://jitty.com/for-sale/london/rural-area-type",
        "https://jitty.com/for-sale/london/flat-property-type?page=2",
        "https://jitty.com/for-sale/london/flat-property-type?sort=price_asc",
        "https://jitty.com/for-sale/paddington-station/travel-by-public-transport/travel-for-60-minutes/look-for-sauna",
        "https://jitty.com/for-sale/london/flat-property-type/",
        "http://jitty.com/for-sale/bath",
        "https://jitty.com/for-sale/greenwich/look-for-waterfront",
        "https://jitty.com/for-sale/look-for-castle",
        "https://jitty.com/for-sale/london/within-5-miles/price-200000-to-500000-gbp/at-least-2-bedrooms",
        "https://jitty.com/for-sale/shoreditch/within-0.5-miles/flat-or-maisonette-property-type",
        "https://www.jitty.com/for-sale/greenwich",
        "https://jitty.com/for-sale/map/london/flat-property-type",
        "https://jitty.com/properties/lrlS0BMHI5MEzJRYM9n9"
    ],
    "proxy": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "GB"
    },
    "ignoreFieldsForChanges": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/jitty-uk-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 = {
    "mode": "search",
    "location": "london",
    "urls": [
        "https://jitty.com/for-sale",
        "https://jitty.com/for-sale/bath",
        "https://jitty.com/for-sale/london",
        "https://jitty.com/for-sale/east-london/flat-property-type",
        "https://jitty.com/for-sale/london/at-least-2-bedrooms/flat-property-type",
        "https://jitty.com/for-sale/london/price-up-to-200000-gbp",
        "https://jitty.com/for-sale/london/rural-area-type",
        "https://jitty.com/for-sale/london/flat-property-type?page=2",
        "https://jitty.com/for-sale/london/flat-property-type?sort=price_asc",
        "https://jitty.com/for-sale/paddington-station/travel-by-public-transport/travel-for-60-minutes/look-for-sauna",
        "https://jitty.com/for-sale/london/flat-property-type/",
        "http://jitty.com/for-sale/bath",
        "https://jitty.com/for-sale/greenwich/look-for-waterfront",
        "https://jitty.com/for-sale/look-for-castle",
        "https://jitty.com/for-sale/london/within-5-miles/price-200000-to-500000-gbp/at-least-2-bedrooms",
        "https://jitty.com/for-sale/shoreditch/within-0.5-miles/flat-or-maisonette-property-type",
        "https://www.jitty.com/for-sale/greenwich",
        "https://jitty.com/for-sale/map/london/flat-property-type",
        "https://jitty.com/properties/lrlS0BMHI5MEzJRYM9n9",
    ],
    "proxy": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "GB",
    },
    "ignoreFieldsForChanges": [],
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/jitty-uk-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 '{
  "mode": "search",
  "location": "london",
  "urls": [
    "https://jitty.com/for-sale",
    "https://jitty.com/for-sale/bath",
    "https://jitty.com/for-sale/london",
    "https://jitty.com/for-sale/east-london/flat-property-type",
    "https://jitty.com/for-sale/london/at-least-2-bedrooms/flat-property-type",
    "https://jitty.com/for-sale/london/price-up-to-200000-gbp",
    "https://jitty.com/for-sale/london/rural-area-type",
    "https://jitty.com/for-sale/london/flat-property-type?page=2",
    "https://jitty.com/for-sale/london/flat-property-type?sort=price_asc",
    "https://jitty.com/for-sale/paddington-station/travel-by-public-transport/travel-for-60-minutes/look-for-sauna",
    "https://jitty.com/for-sale/london/flat-property-type/",
    "http://jitty.com/for-sale/bath",
    "https://jitty.com/for-sale/greenwich/look-for-waterfront",
    "https://jitty.com/for-sale/look-for-castle",
    "https://jitty.com/for-sale/london/within-5-miles/price-200000-to-500000-gbp/at-least-2-bedrooms",
    "https://jitty.com/for-sale/shoreditch/within-0.5-miles/flat-or-maisonette-property-type",
    "https://www.jitty.com/for-sale/greenwich",
    "https://jitty.com/for-sale/map/london/flat-property-type",
    "https://jitty.com/properties/lrlS0BMHI5MEzJRYM9n9"
  ],
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "GB"
  },
  "ignoreFieldsForChanges": []
}' |
apify call abotapi/jitty-uk-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,abotapi/jitty-uk-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/5fpMBVDNK8cYwWRHg/builds/DUBr3mncWSk6aaWSU/openapi.json
