# Gumtree.com Scraper - Classifieds, Prices, Sellers & Reviews (`abotapi/gumtree-uk-scraper`) Actor

Scrape Gumtree.com classifieds across motors, property, jobs, services, pets and goods for sale. Extract titles, descriptions, prices, photos, locations, listing attributes, seller ratings, star distributions and reviews. Supports keyword, category, location and URL modes.

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

## Pricing

from $1.30 / 1,000 listing results

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

## Gumtree UK Scraper: Listings, Prices, Seller Ratings and Contact Details

Gumtree UK Scraper turns gumtree.com classifieds into structured data. Get the title, price, photos, category attributes and map location for any listing across every vertical, motors, property, jobs, services, pets, community and the general for-sale categories, plus the seller's aggregate rating, star breakdown and individual reviews once full listing detail is on. Search by category, location and keyword, or paste a gumtree.com results URL you already refined in a browser, then export to JSON, CSV or Excel, or read the dataset through the API.

### Why This Scraper?

- **Two ways in.** Build a search from category, location and keyword filters, or paste a gumtree.com results URL you already refined in a browser, sub-categories and the sort, price, keyword, location, make and seller-type filters included.
- **Every vertical, one record shape.** Motors, property, jobs, services, pets, community and the general for-sale categories all come back with the same clean fields.
- **Full listing detail on demand.** Switch on the full description, map coordinates, postcode and the richer grouped attribute set per run, and pay only when a listing is actually opened.
- **Seller trust signals.** Aggregate rating, the count per star, individual reviews and activity stats, captured from the listing page.
- **Optional seller phone reveal.** Get the seller's full number instead of Gumtree's masked form, with a clear per-listing status whenever one is not available.
- **Built for schedules.** Incremental mode returns only new, changed, reappeared or expired listings on recurring runs, and Resume continues one interrupted crawl without re-billing what it already collected.
- **Fails loud, not quiet.** A run that could not read the site stops with a clear message instead of reporting a false "no listings".

### Use Cases

- **Car buyers and dealers:** track new and price-changed listings for specific makes and models to spot underpriced cars quickly.
- **Letting agents and house hunters:** monitor new property listings in target towns as soon as they appear.
- **Resellers and price researchers:** benchmark second-hand prices for a product category across the whole UK.
- **Local trade and job seekers:** watch new services and jobs postings in a region.
- **Buyer due diligence:** check a seller's aggregate rating, star breakdown and review history before making contact.

### Data You Get

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

| Field | Example |
| --- | --- |
| `id` | `"3300118842"` |
| `url` | `"https://www.gumtree.com/p/renault-clio/renault-clio-1-5-dci-dynamique/3300118842"` |
| `title` | `"Renault Clio 1.5 dCi Dynamique, 2017, Diesel"` |
| `price` / `priceText` | `4250.0` / `"£4,250"` |
| `currency` | `"GBP"` |
| `vertical` | `"motors"` (also `"for-sale"`, `"jobs"`) |
| `categoryName` | `"Cars"` |
| `location` / `distance` | `"Bristol"` / `"5 miles"` |
| `postedDate` / `postedTimestamp` | `"3 days ago"` / `"2026-06-20T09:15:00Z"` |
| `attributes` | `[{ "name": "Mileage", "value": "58,400", "key": "vehicle_mileage", "unit": "miles" }]` |
| `images` / `imageCount` | array of photo URLs / `9` |
| `urgent` / `featured` / `premium` | `false` / `true` / `false` |
| `detailFetched` | `true` (only once detail enrichment has run for this listing) |
| `description` | `"Well looked after, one previous owner, full service history..."` |
| `latitude` / `longitude` / `postcode` | `51.4545` / `-2.5879` / `"BS1 4DJ"` |
| `seller.name` / `seller.type` | `"Tom H"` / `"private"` (or `"trade"`) |
| `seller.rating` / `seller.reviewCount` | `4.6` / `18` |
| `seller.ratingDistribution` | `{ "1": 0, "2": 0, "3": 1, "4": 3, "5": 14 }` |
| `seller.phone` / `seller.phoneMasked` / `seller.phoneStatus` | `"07700 900123"` / `"0770090XXXX"` / `"revealed"` |
| `seller.postingSince` / `seller.totalAdvertCount` | `"2 years"` / `5` |
| `scrapedAt` | `"2026-06-23T10:00:00Z"` |

Every record also carries category ids (`l1CategoryId`, `l2CategoryId`), ad-type flags (`standout`, `bumpup`, `proAccount`, `favouriteCount`), and address fields (`area`, `subArea`, `address`); with detail enrichment on, motors listings can additionally carry `vehicleHistoryCheck`, `videoUrls` and `questionsAndAnswers`, and services sellers carry a `seller.skills` list. In incremental mode every record also carries `changeType`, `changedFields`, `firstSeenAt` and `lastSeenAt`.

### How to Use

1. Pick a **mode**: `search` (build the query from category, location and keyword) or `url` (paste a gumtree.com results URL).
2. In search mode, choose a **category**, an optional **location** and **keyword**, then narrow by price and sort order if you need to.
   Add more towns in **More locations** (`locations`); each location (and, for API callers passing a list, each keyword) is searched separately and the results are merged and de-duplicated. `sortBy` also accepts `date` (same as `most_recent`) and `price` (same as `price_asc`). Every row carries `image` (the first listing photo) alongside the full `images` list; `description` is filled when full listing detail is on. The site ignores a search-radius or posted-time parameter, so those filters are not offered.
3. Turn on **Fetch full listing detail** for the description, map location and seller rating and reviews, and **Also reveal the seller's phone number** if you need the full contact number.
4. Set **Max listings** and **Max pages** to bound the run, then click **Start**. Download as JSON, CSV or Excel, or read the dataset through the API.

**Cars in a price band, with full detail:**

```json
{
  "mode": "search",
  "category": "cars",
  "location": "London",
  "minPrice": 5000,
  "maxPrice": 8000,
  "fetchDetails": true,
  "maxItems": 50
}
```

**A national keyword search, results-page fields only:**

```json
{
  "mode": "search",
  "category": "all",
  "keywords": "iphone",
  "fetchDetails": false,
  "maxItems": 30
}
```

**Paste a results URL you already refined in a browser:**

```json
{
  "mode": "url",
  "urls": ["https://www.gumtree.com/cars-vans-motorbikes/cars/uk/london"],
  "fetchDetails": false,
  "maxPages": 2,
  "maxItems": 60
}
```

**Reveal the seller's phone number:**

```json
{
  "mode": "search",
  "category": "cars",
  "location": "Manchester",
  "fetchDetails": true,
  "revealSellerPhone": true,
  "maxItems": 20
}
```

`urls` accepts gumtree.com category, location and keyword-search results pages (the sub-category and the sort, price, keyword, location, make and seller-type filters in the link are kept; any other filter parameter is dropped; a `/pageN` or `?page=N` link starts at that page and then follows the site's own next-page links), and single listing links of the form `/p/<slug>/<id>`, which return that one listing (with the detail fields when full listing detail is on). Links on gumtree.com, www.gumtree.com, http or https are accepted. A seller profile link, the m.gumtree.com host, a link on any other site (including gumtree.com.au) is skipped with a warning in the run log, and a `/p/<id>` link without the slug is attempted with a warning because it is not confirmed to resolve.

**Behaviour change:** if you switch to URL mode and leave `urls` untouched, the actor now runs the 13 sample links below (one per distinct URL shape; a page-2 link starts at page 2 and returns its own rows), capped by Max items, instead of one sample link.

| Shape | Example |
|---|---|
| category location | `https://www.gumtree.com/cars-vans-motorbikes/cars/uk/london` |
| category nationwide | `https://www.gumtree.com/cars-vans-motorbikes/cars/uk` |
| forsale root nationwide | `https://www.gumtree.com/for-sale/uk` |
| forsale location | `https://www.gumtree.com/for-sale/uk/london` |
| jobs location | `https://www.gumtree.com/jobs/uk/london` |
| pets location | `https://www.gumtree.com/pets/uk/london` |
| legacy property path | `https://www.gumtree.com/property-to-rent/london` |
| category page2 | `https://www.gumtree.com/cars-vans-motorbikes/cars/uk/london/page2` |
| category filtered sorted | `https://www.gumtree.com/cars-vans-motorbikes/cars/uk/london?sort=price_lowest_first&min_price=1000&max_price=5000` |
| keyword location | `https://www.gumtree.com/search?search_category=all&q=iphone&search_location=london` |
| keyword no location | `https://www.gumtree.com/search?search_category=all&q=ford+focus` |
| keyword page2 | `https://www.gumtree.com/search?q=iphone&search_location=london&page=2` |
| listing detail | `https://www.gumtree.com/p/iphone/apple-iphone-17-pro-unlocked/1803255814` |

An unknown Location in search mode returns no listings and the run log and status message say the location was not found.

#### Run it from your code

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/gumtree-uk-scraper").call(run_input={
    "mode": "search", "category": "cars", "location": "London", "maxItems": 50
})
for listing in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(listing["title"], listing["priceText"])
```

JavaScript:

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

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/gumtree-uk-scraper').call({
  mode: 'search', category: 'cars', location: 'London', maxItems: 50,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

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

#### Seller phone numbers

Gumtree shows a seller's phone number in full only to a signed-in visitor; everyone else sees it masked, for example `0770090XXXX`. Turn on **Also reveal the seller's phone number** and the actor signs in through an account it manages and caches securely for itself, reused by every later run, so each listing then carries the full number in `seller.phone`. It needs detail enrichment, which is switched on automatically, and it adds no extra request or charge per listing: the number arrives in the detail fetch that already happens.

Not every seller publishes a number, and `seller.phoneStatus` is only set at all when the listing page itself was read (it stays `null` if detail enrichment was off, the fetch failed, or a near-timeout shortcut skipped it). When it is set, the values are:

| `seller.phoneStatus` | Meaning |
| --- | --- |
| `revealed` | `seller.phone` holds the full number |
| `no-phone` | Gumtree confirmed this seller published no number at all |
| `not-requested` | the option was off for this run, or sign-in itself failed before any reveal was attempted |
| `session-expired` | signed-in access lapsed mid-run; it renews automatically on the next run |
| `refused` | the site did not honour the reveal for this particular listing |
| `unavailable` | this listing's contact details could not be read at all |

`seller.phoneMasked` always carries the masked form Gumtree shows publicly, so nothing is lost either way. Phone numbers are personal data: keep collecting and using them lawful and proportionate under UK GDPR and Gumtree's terms, as the operator of this run.

#### Resume and recurring updates

- **Resume** (`resumeFromRunId`) continues one interrupted crawl: paste its run or dataset id and this run still walks every result page from the start of the search, but skips every listing id that run already collected, so pagination is never cut short by the dedup and you are not billed twice for the same listing.
- **Incremental mode** (`incrementalMode`) is for scheduling this actor against the same search repeatedly. Each listing is classified `NEW`, `UPDATED` (with `changedFields`), `UNCHANGED` (suppressed and not billed unless `emitUnchanged` is on), `REAPPEARED`, or `EXPIRED`. `EXPIRED` is only produced, and a listing is only marked gone in the stored state, after a run that reaches the natural end of results for every search in the call, with `emitExpired` on and no Resume id set; a capped, time-limited, or resumed run leaves the previous state untouched instead of guessing that a listing is gone. `REAPPEARED` can therefore only happen for a listing a prior run already marked gone this way. `stateKey` names or shares the stored state; leave it empty and the actor derives one automatically from the mode, category, location, keyword, sort, price filters and the detail-enrichment toggle, so two different filter setups never share a baseline. Fields that drift without the listing changing (`scrapedAt`, the relative posted age `postedDate` and the `Posted` attribute, and `image`, a derived copy of the first photo URL) are excluded from change detection by default; add others such as `favouriteCount` or `distance` with `ignoreFieldsForChanges`. They remain in the output. A run that starts from a page-N URL (`?page=N` with N above 1) never marks anything EXPIRED. With Incremental mode off, output is exactly as before.

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

Optionally pipe the scraped listings 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 listing, not the full JSON. Each listing 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 listings 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` | Pick `search` to build the query from the filters below, or `url` to paste gumtree.com results URLs. |
| `urls` | array | the 13 sample links in the table above | gumtree.com results pages or single listing links (`/p/<slug>/<id>`) to read (URL mode). |
| `category` | string | `all` | Category to search: `all` (for-sale goods), `motors`, `cars`, `property`, `jobs`, `services`, `pets`, or `community`. |
| `location` | string | (none, prefill `London`) | Town, city or region. Empty searches all of the UK. |
| `locations` | array | (none) | Extra towns, cities or regions searched in addition to Location; each is searched separately and results are merged and de-duplicated. Ignored in URL mode. |
| `keywords` | string | (none) | Free-text keyword search, optionally narrowed by location. |
| `sortBy` | string | (none, site's relevance order) | `best_match`, `most_recent`, `price_asc`, `price_desc`, or `nearest`; `date` is accepted as an alias of `most_recent` and `price` of `price_asc`. |
| `minPrice` | integer | (none) | Only return listings priced at or above this amount (GBP). |
| `maxPrice` | integer | (none) | Only return listings priced at or below this amount (GBP). |
| `fetchDetails` | boolean | `true` | Open each listing for its full description, map location, richer attributes and the seller's rating, reviews and activity stats. Adds a detail-enrichment charge per listing actually opened. |
| `revealSellerPhone` | boolean | `false` | Return the seller's full phone number in `seller.phone` instead of Gumtree's masked form. Needs detail enrichment, which is switched on automatically; adds no extra charge. |
| `maxItems` | integer | `100` | Maximum listings to return across the whole run. `0` = no limit (bounded by Max pages, at most 50 pages per search). Capped at 1,000,000. |
| `maxPages` | integer | `0` | Result pages to walk forward per search (30 listings per page). 0 uses the standard 5 pages; the actor never walks more than 50 pages per search. |
| `resumeFromRunId` | string | (none) | Continue one interrupted crawl: listings already collected under this run/dataset id are skipped. |
| `incrementalMode` | boolean | `false` | For scheduled runs of the same search: classify each listing as NEW / UPDATED / UNCHANGED / REAPPEARED / EXPIRED against the previous run instead of returning everything again. |
| `stateKey` | string | (none, auto-derived from the filters) | Optional label to isolate this search's incremental state. |
| `emitUnchanged` | boolean | `false` | Also return (and bill) UNCHANGED listings instead of suppressing them. |
| `emitExpired` | boolean | `false` | Also return (and bill) listings no longer found, once, after a run that completes a full scan of every search. |
| `ignoreFieldsForChanges` | array | `[]` | Extra field names (or dotted nested paths such as `seller.name`) that never count as a change in incremental mode. They stay in the output. Always ignored: `scrapedAt`, `postedDate`, the relative `Posted` attribute and `image` (a derived copy of the first photo URL). Add `favouriteCount` or `distance` here if you do not want a changed watcher count to mark a listing UPDATED. |
| `proxy` | object | `{ "useApifyProxy": true }` | Connection settings; the default automatic setting rotates connections for you. |
| `mcpConnectors` | array | (none) | Optionally send a summary of each listing 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": "3300118842",
  "url": "https://www.gumtree.com/p/renault-clio/renault-clio-1-5-dci-dynamique/3300118842",
  "title": "Renault Clio 1.5 dCi Dynamique, 2017, Diesel",
  "price": 4250.0,
  "priceText": "£4,250",
  "currency": "GBP",
  "categoryId": "9311",
  "categoryName": "Cars",
  "vertical": "motors",
  "location": "Bristol",
  "distance": "5 miles",
  "postedDate": "3 days ago",
  "postedTimestamp": "2026-06-20T09:15:00Z",
  "shortDescription": "One owner, full service history, new MOT",
  "description": "Well looked after Renault Clio, one previous owner, full service history, two keys, recently serviced with a new MOT.",
  "images": [
    "https://img.gumtree.com/bbbbbbbb/5555555555_6666666666/max800",
    "https://img.gumtree.com/bbbbbbbb/7777777777_8888888888/max800"
  ],
  "imageCount": 9,
  "attributes": [
    { "name": "Make", "value": "Renault", "key": "vehicle_make" },
    { "name": "Year", "value": "2017", "key": "vehicle_registration_year" },
    { "name": "Mileage", "value": "58,400", "key": "vehicle_mileage", "unit": "miles" },
    { "name": "Fuel type", "value": "Diesel", "key": "vehicle_fuel_type" }
  ],
  "latitude": 51.4545,
  "longitude": -2.5879,
  "postcode": "BS1 4DJ",
  "detailFetched": true,
  "seller": {
    "name": "Tom H",
    "type": "private",
    "rating": 4.6,
    "reviewCount": 18,
    "ratingDistribution": { "1": 0, "2": 0, "3": 1, "4": 3, "5": 14 },
    "reviews": [
      { "rating": 5, "text": "Straightforward sale, car as described.", "date": "2026-05-02" }
    ],
    "postingSince": "2 years",
    "totalAdvertCount": 5,
    "phone": "07700 900123",
    "phoneMasked": "0770090XXXX",
    "phoneStatus": "revealed"
  },
  "scrapedAt": "2026-06-23T10:00:00Z"
}
```

#### Output views

The dataset has these views in the Console: **Listings Overview**, **Seller & Rating**, **Seller Contact**, **Listing Detail** (detail enrichment) and **Changes** (incremental mode). Every view reads the same records; none changes the data.

### Plan Requirement

Measured on the main page shapes (search, category and listing pages), the site was readable from a datacenter connection, so the default Apify proxy setting is the starting point and residential is not required. Some paths (seller profile links and slug-less `/p/<id>` links) return a bot-check stub instead of the page and are not guaranteed to load. The run retries with a different connection when one is refused. For large or frequent runs, the residential proxy group gives more headroom; pick it under Proxy and connection.

If the residential connection is refused (Apify free plans do not include residential proxies) the run logs this warning:

```
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.
```

and, when the backup serves data, "Served over the backup connection (the default connection was unavailable)." A run that cannot read any page ends with one of these messages:

- "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."
- "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 Gumtree pages. Upgrade at https://apify.com/pricing or supply your own proxy URLs, then try again."
- "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."

Billing follows the Pricing tab: a run start event, a per-listing event for each listing returned, and a detail-enrichment event per listing, charged only for listings where Fetch full listing detail actually opened that listing's page. Revealing the seller's phone number adds no charge of its own.

### FAQ

#### How much does it cost?

You pay a run start fee, a charge per listing returned, and a further detail-enrichment charge per listing, but only for listings where Fetch full listing detail actually opened the listing page (a listing suppressed by incremental mode is never charged). Revealing the seller's phone number adds no extra charge of its own; it reuses that same detail fetch. The **Pricing** tab shows the current rates. Use **Max listings** and **Max pages** to cap the cost of any run.

#### Is it legal to scrape Gumtree?

This actor collects only publicly available classified listings. Seller names, phone numbers and other contact details are personal data: collecting and using them is subject to UK GDPR and to Gumtree's terms, and that responsibility sits with you as the operator. Keep usage lawful and proportionate, and get legal advice if you plan commercial redistribution.

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

Yes. Schedule the actor against the same search and turn on **Incremental mode**. Each run then classifies every listing as NEW, UPDATED, UNCHANGED, REAPPEARED or EXPIRED against the previous run, and UNCHANGED listings are suppressed (and not billed) unless you turn on **Also return UNCHANGED listings**.

#### Why don't I see any REAPPEARED or EXPIRED listings?

EXPIRED rows, and the underlying "this listing is gone" state, are only produced after a run that reaches the natural end of results for every search in the call, with **Also return EXPIRED listings** on and no Resume id set. A capped run, a time-limited run, or one using Resume, leaves the previous state exactly as it was rather than guessing a listing is gone. REAPPEARED can only ever happen for a listing a prior run already marked gone this way, so a search that has never yet completed a full scan with that option on will never show either changeType.

#### Does Resume work if I run the exact same search again?

Yes. Paste the previous run or dataset id into **Resume from run/dataset ID** and this run still walks every result page from the start of the search, but skips any listing id already collected there, so pagination continues normally and you are not billed twice for the same listing.

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

If every result page comes back unreadable, the run stops with a clear message instead of reporting zero listings, so a genuine connection problem is never confused with an empty search. If seller phone numbers were requested and every attempted reveal came back `session-expired` or `refused` with none `revealed`, the run also fails loudly rather than returning a column of nulls; switch the phone option off to keep collecting every other field. If sign-in itself fails at the start of the run, reveal is skipped entirely rather than failing the run: every record gets `phoneStatus: "not-requested"` instead. A search that genuinely has no matching listings still ends as a clean, successful empty result.

#### 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 a summary of each listing into Notion, Linear or Airtable.

### 🔗 Want more Gumtree data?

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

<table>
<tr><td>🏷️ <a href="https://apify.com/abotapi/gumtree-au-scraper"><b>Gumtree AU Scraper</b></a><br>Scrape gumtree.com.au classifieds across every vertical: for-sale goods, motors, real...</td><td>🚗 <a href="https://apify.com/abotapi/trademe-co-nz-scraper"><b>Trade Me NZ Scraper</b></a><br>Scrape trademe.co.nz across all five sections: Marketplace goods and auctions, Property...</td></tr>
<tr><td>🏷️ <a href="https://apify.com/abotapi/subito-it-scraper"><b>Subito.it Scraper</b></a><br>Scrape Subito.it listings across cars, real estate, marketplace, jobs, and more. Search...</td><td>🚗 <a href="https://apify.com/abotapi/willhaben-at-scraper"><b>Willhaben.at Scraper</b></a><br>Scrape Willhaben.at listings into clean JSON with 40+ structured fields, including...</td></tr>
<tr><td>🚗 <a href="https://apify.com/abotapi/dubizzle-com-scraper"><b>Dubizzle.com Scraper</b></a><br>Scrape dubizzle.com across the UAE for property, motors, and agent listings. Search by...</td><td>🚗 <a href="https://apify.com/abotapi/craigslist-classifieds-scraper"><b>Craigslist Scraper</b></a><br>Scrape Craigslist postings in any of 700+ cities worldwide: price, title, posting text...</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/gumtree-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`):

Search mode = build the query from the category / location / keyword filters below. URL mode = paste any gumtree.com results or listing URL you already refined in a browser (best for complex filters and sub-categories).

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

gumtree.com results-page URLs (category, location, keyword search, page N, filters) or single listing URLs (/p/<slug>/<id>). Tip: open gumtree.com, choose a category + location + filters, then paste the resulting URL here. In URL mode all the filter fields below are ignored. Left untouched, this runs the 13 sample URLs shown (capped by Max items).

## `category` (type: `string`):

Top-level category to search. 'All categories' searches the for-sale goods; the other options cover Gumtree's main verticals. For a specific sub-category, use URL mode with a browsed URL.

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

Town, city or region to search in (e.g. 'London', 'Manchester', 'Birmingham', 'West Midlands'). Leave empty to search all of the UK.

## `locations` (type: `array`):

Optional extra towns, cities or regions. Each is searched separately (combined with Location above and with the keyword) and results are merged and de-duplicated. Ignored in URL mode.

## `keywords` (type: `string`):

Free-text keyword to search for (e.g. 'ford focus', 'iphone 15'). When set, the scraper runs a keyword search (optionally narrowed to the location above). Optional — leave empty to browse the whole category. API callers may also pass a list of keywords; each is searched separately and results are merged.

## `sortBy` (type: `string`):

How to order results. 'date' is accepted as an alias of 'most_recent' and 'price' of 'price_asc'.

## `minPrice` (type: `integer`):

Only return listings priced at or above this amount.

## `maxPrice` (type: `integer`):

Only return listings priced at or below this amount.

## `fetchDetails` (type: `boolean`):

Adds a detail-enrichment charge per enriched listing.

## `revealSellerPhone` (type: `boolean`):

Gumtree shows a seller's phone number only to signed-in visitors; to everyone else it is masked (e.g. 0770090XXXX). Turn this on and the scraper uses its own free Gumtree account so each listing carries the full number in seller.phone. It needs detail enrichment, which is switched on automatically, and adds no extra request or charge per listing. Every record also carries seller.phoneStatus, so a listing whose seller published no number is never confused with one that could not be read.

## `maxItems` (type: `integer`):

Maximum number of listings to return across the whole run. 0 = no limit (bounded by Max pages, at most 50 pages per search). Capped at 1,000,000.

## `maxPages` (type: `integer`):

How many result pages to walk forward per search (30 listings per page). 0 = the standard 5 pages. Hard-capped at 50 pages per search; the site serves no more.

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

Apify Proxy is used to reach the site reliably. The default automatic proxy works well; IP rotation is handled for you.

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

Paste a previous run id or dataset id to continue an interrupted crawl: listings already collected there are skipped so this run returns only the delta. Leave empty for a normal run.

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

For a search you run on a schedule. When on, the actor remembers this search's previous run and classifies every listing as NEW / UPDATED / UNCHANGED / REAPPEARED / EXPIRED instead of returning the same listings every time. Default off (every run returns the full result set as today).

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

Optional label to isolate this search's incremental state, useful if you run the same filters under two different schedules. Leave empty to derive the state automatically from the mode/category/location/keyword/sort/price/URL filters and the detail-enrichment toggle — two different filter setups never share a baseline.

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

When on, listings with no change since the previous incremental run are still returned (and billed) instead of being suppressed. Off by default so a recurring run bills only for what changed.

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

When on, listings that were tracked before but are no longer found are returned once (and billed) with changeType EXPIRED, then dropped from tracking. Only emitted after a run that reached the natural end of results for every search — a capped or time-limited run never emits EXPIRED rows, to avoid wrongly flagging a live listing as gone. Off by default.

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

Field names (or dotted nested paths such as seller.name) that never count as a change in incremental mode. They stay in the output but a listing whose only difference is in these fields is UNCHANGED and not listed in changedFields. Already ignored by default: scrapedAt, postedDate, the relative 'Posted' attribute and image (a derived copy of the first photo URL). Add favouriteCount or distance here if a changed watcher count should not mark a listing UPDATED.

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

Optionally send scraped results into 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; the full record stays in the dataset. 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",
  "urls": [
    "https://www.gumtree.com/cars-vans-motorbikes/cars/uk/london",
    "https://www.gumtree.com/cars-vans-motorbikes/cars/uk",
    "https://www.gumtree.com/for-sale/uk",
    "https://www.gumtree.com/for-sale/uk/london",
    "https://www.gumtree.com/jobs/uk/london",
    "https://www.gumtree.com/pets/uk/london",
    "https://www.gumtree.com/property-to-rent/london",
    "https://www.gumtree.com/cars-vans-motorbikes/cars/uk/london/page2",
    "https://www.gumtree.com/cars-vans-motorbikes/cars/uk/london?sort=price_lowest_first&min_price=1000&max_price=5000",
    "https://www.gumtree.com/search?search_category=all&q=iphone&search_location=london",
    "https://www.gumtree.com/search?search_category=all&q=ford+focus",
    "https://www.gumtree.com/search?q=iphone&search_location=london&page=2",
    "https://www.gumtree.com/p/iphone/apple-iphone-17-pro-unlocked/1803255814"
  ],
  "category": "all",
  "location": "London",
  "fetchDetails": true,
  "revealSellerPhone": false,
  "maxItems": 20,
  "maxPages": 0,
  "proxy": {
    "useApifyProxy": true
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "ignoreFieldsForChanges": [],
  "maxNotifyListings": 50
}
```

# Actor output Schema

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

Listings overview view of the dataset.

## `detail` (type: `string`):

Listing detail view of the dataset.

## `seller` (type: `string`):

Seller & rating view of the dataset.

## `sellerContact` (type: `string`):

Seller contact view of the dataset.

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

Changes (incremental) view of the dataset.

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

Individual listing records with price, location, image URLs, category attributes, and seller info.

## `output` (type: `string`):

Run summary with total listings and request count.

# 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 = {
    "urls": [
        "https://www.gumtree.com/cars-vans-motorbikes/cars/uk/london",
        "https://www.gumtree.com/cars-vans-motorbikes/cars/uk",
        "https://www.gumtree.com/for-sale/uk",
        "https://www.gumtree.com/for-sale/uk/london",
        "https://www.gumtree.com/jobs/uk/london",
        "https://www.gumtree.com/pets/uk/london",
        "https://www.gumtree.com/property-to-rent/london",
        "https://www.gumtree.com/cars-vans-motorbikes/cars/uk/london/page2",
        "https://www.gumtree.com/cars-vans-motorbikes/cars/uk/london?sort=price_lowest_first&min_price=1000&max_price=5000",
        "https://www.gumtree.com/search?search_category=all&q=iphone&search_location=london",
        "https://www.gumtree.com/search?search_category=all&q=ford+focus",
        "https://www.gumtree.com/search?q=iphone&search_location=london&page=2",
        "https://www.gumtree.com/p/iphone/apple-iphone-17-pro-unlocked/1803255814"
    ],
    "location": "London",
    "maxItems": 20,
    "proxy": {
        "useApifyProxy": true
    },
    "ignoreFieldsForChanges": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/gumtree-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 = {
    "urls": [
        "https://www.gumtree.com/cars-vans-motorbikes/cars/uk/london",
        "https://www.gumtree.com/cars-vans-motorbikes/cars/uk",
        "https://www.gumtree.com/for-sale/uk",
        "https://www.gumtree.com/for-sale/uk/london",
        "https://www.gumtree.com/jobs/uk/london",
        "https://www.gumtree.com/pets/uk/london",
        "https://www.gumtree.com/property-to-rent/london",
        "https://www.gumtree.com/cars-vans-motorbikes/cars/uk/london/page2",
        "https://www.gumtree.com/cars-vans-motorbikes/cars/uk/london?sort=price_lowest_first&min_price=1000&max_price=5000",
        "https://www.gumtree.com/search?search_category=all&q=iphone&search_location=london",
        "https://www.gumtree.com/search?search_category=all&q=ford+focus",
        "https://www.gumtree.com/search?q=iphone&search_location=london&page=2",
        "https://www.gumtree.com/p/iphone/apple-iphone-17-pro-unlocked/1803255814",
    ],
    "location": "London",
    "maxItems": 20,
    "proxy": { "useApifyProxy": True },
    "ignoreFieldsForChanges": [],
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/gumtree-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 '{
  "urls": [
    "https://www.gumtree.com/cars-vans-motorbikes/cars/uk/london",
    "https://www.gumtree.com/cars-vans-motorbikes/cars/uk",
    "https://www.gumtree.com/for-sale/uk",
    "https://www.gumtree.com/for-sale/uk/london",
    "https://www.gumtree.com/jobs/uk/london",
    "https://www.gumtree.com/pets/uk/london",
    "https://www.gumtree.com/property-to-rent/london",
    "https://www.gumtree.com/cars-vans-motorbikes/cars/uk/london/page2",
    "https://www.gumtree.com/cars-vans-motorbikes/cars/uk/london?sort=price_lowest_first&min_price=1000&max_price=5000",
    "https://www.gumtree.com/search?search_category=all&q=iphone&search_location=london",
    "https://www.gumtree.com/search?search_category=all&q=ford+focus",
    "https://www.gumtree.com/search?q=iphone&search_location=london&page=2",
    "https://www.gumtree.com/p/iphone/apple-iphone-17-pro-unlocked/1803255814"
  ],
  "location": "London",
  "maxItems": 20,
  "proxy": {
    "useApifyProxy": true
  },
  "ignoreFieldsForChanges": []
}' |
apify call abotapi/gumtree-uk-scraper --silent --output-dataset

```

## MCP server setup

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