# Gumtree Scraper — UK Listings, Prices & New Ads Alerts (`northbell/gumtree-scraper`) Actor

Gumtree UK listings for any search: title, price, town, date, seller type, photo and a description snippet. Run it again or on a schedule to get only the new listings and the price drops since the last run. Keywords or gumtree.com URLs. No login.

- **URL**: https://apify.com/northbell/gumtree-scraper.md
- **Developed by:** [Northbell](https://apify.com/northbell) (community)
- **Categories:** E-commerce, Lead generation
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 1,000 listings

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 Scraper — UK Listings, Prices & New Ads Alerts

Give it keywords or Gumtree search links and get one clean row per listing: **title, price, town, date, seller type (private or business), condition, photo and a description snippet**. **$1.00 per 1,000 listings**, no login, no API key. Gumtree shows at most 50 pages of about 25 to 30 listings for any search, so one search returns roughly 1,250 to 1,500 listings at most.

Run it again — or put it on a schedule — and every row also tells you **what changed since the last run**: `isNew`, `previousPrice` and `priceChange` (a negative number is a price drop). Switch on *Only new listings and price changes* and the run returns just those, so you pay only for the rows you act on.

Fixed 22 Oct 2026: when the previous run stopped before the end of the results (at *Max listings*, at your charge limit or on a page error), listings it had simply not reached counted as new, so with *Only new listings and price changes* a second run could return older listings as new and charge for them. After such a run, new now means posted after the newest listing it saw (with two hours' slack for listings that appear late); after a run that read the whole list, every listing it did not see is still new.

### What you get

| Field | What it is |
|---|---|
| `type`, `observedAt` | the row type (`listing`) and when it was read |
| `search`, `position` | the search line that found it, and its place in that search's results |
| `adId`, `url`, `title` | the listing |
| `price`, `priceText`, `currency`, `pricePeriod` | price in pounds as a number (`889`), as Gumtree writes it (`£889.00`), and `GBP`; `pricePeriod` is `month` or `week` for rents written `£725.00pm` or `£225.00pw`, otherwise `null`; `price` is `null` when the ad shows no price (job ads show their salary under `attributes`, and most services and community ads have no price); a price of `0` is what Gumtree shows as `£0.00`, which is a real "free" on free items but a placeholder on a few ads such as a rental |
| `location`, `distanceMiles` | the town and area as Gumtree shows it (`Patchway, Bristol`); miles from the place you searched (only filled when you set a location) |
| `postedAt`, `postedText` | the listing date Gumtree reports (ISO time) and its own wording (`5 hours ago`) |
| `category`, `sellerType`, `condition` | Gumtree's category name, the seller type as Gumtree shows it (`Private`, `Business`, `Trade` or `Agency`), and the condition the seller chose (when the category has one) |
| `imageUrl`, `imageCount` | the first photo and how many photos the ad has |
| `descriptionSnippet`, `attributes` | the first lines of the description, and the details Gumtree lists for the category (model, storage and colour for phones; make, year, mileage and fuel for cars) |
| `isPromoted`, `isUrgent`, `shippingAvailable` | paid promotion, the urgent badge, and whether the seller offers delivery |
| `isNew`, `firstSeenAt`, `timesSeen` | whether this search has shown the listing before (`null` on the first run), when this Actor first saw it, and in how many runs |
| `previousPrice`, `priceChange`, `priceChangePercent` | the price at the previous run and the difference (negative = cheaper); `priceChange` is `0` when nothing changed, `null` on the first run |

Every run also adds one free **summary** row (`type: "summary"`): per search, how many listings Gumtree reports in total, how many pages were read, how many are new and how many changed price. Rows have `type`: `listing`, `summary` or `error`.

### Run it again and again

- **On a schedule** — save your input as a task and add a **Schedule**: the same searches every hour or every morning. Send each run to Google Sheets, Slack or email with an integration on the task.
- **Watch for changes** — Turn on **Only new listings and price changes**.
- **In bulk** — Put every search in **Searches** in one run.

### Use it for

- **Deal hunting** — "iPhone 15 under £400 in and around Manchester", every few hours, only the new ones
- **Reselling** — catch listings soon after they appear (newest first) and spot sellers who drop their price
- **Price research** — export a model's asking prices by town to Sheets and watch them move week by week

### Input

```json
{
  "searches": ["iphone 15", "https://www.gumtree.com/search?search_category=all&q=mountain+bike&sort=date"],
  "location": "manchester",
  "distance": "15",
  "maxPrice": 400,
  "maxListingsPerSearch": 100,
  "onlyNew": true
}
```

Each line in *Searches* is a keyword or a link copied from gumtree.com (a search or a category page). A link keeps its own filters and sort order; location, distance, price, category and sorting apply to keywords. For filters this Actor does not have (seller type, condition, model, colour), set them on gumtree.com and paste the link.

What the Actor remembers is kept per search (keyword plus filters) in a named key-value store in your Apify account, so the second run of the same search already shows what is new. Schedule it (Apify → Schedules) to run every few hours or once a day.

### Pricing

**$1.00 per 1,000 listings**, plus $0.01 per run. Error rows and the summary row are free. The $0.01 run-start fee is the one charge every run pays, even one that returns nothing. With *Only new listings and price changes* on, you pay only for the rows returned.

### Notes

- **Gumtree limits how many pages one connection may read: about 5 per 18 minutes.** In our tests the sixth page read from one connection was always answered with Gumtree's verification page instead of results, whatever the pause between reads (1 to 30 seconds), and reads were accepted again within about 20 minutes. The Actor never tries to get past that check. It reads up to 5 pages (about 100 to 150 listings) straight away, which takes well under a minute, and for anything beyond that it waits until the oldest read is 18 minutes old. So *Max listings per search* up to about 100 is fast, while 1,000 listings (about 40 page reads, 5 per 18 minutes) would take about two hours — set the run timeout to match, or schedule smaller runs with *Only new listings*. The run log tells you the expected time when more than 5 page reads are needed. If the next wait would run past the run's timeout, the Actor stops reading before that, saves what it has read and adds an error row, instead of being cut off with rows unsaved.
- If Gumtree refuses a read anyway (another user on the same connection may have used the allowance), the Actor returns the listings it already has, adds an error row, and skips the rest of the searches instead of pressing on. Run it again after about 20 minutes.
- Gumtree applies a price limit only inside the category it narrows a keyword to (for "iphone 15" the *Apple iPhone* category), so with a price set the Actor reads the first page a second time there. In some categories Gumtree does not apply the limit at all (in our tests Property in Manchester: with a limit of £700, most of the 25 rentals returned were still above it and the total did not change). The Actor then drops the listings outside your range itself, after reading them; they count towards *Max listings per search*, so you get fewer rows than the maximum, and the summary row and the run log say so. Raise *Max listings per search* to read further down the list. Rents are compared as written (a weekly £225 is compared with your limit as £225). Promoted ads ignore price limits on Gumtree; the Actor drops the ones outside your range. Listings without a price are kept.
- *Location* takes the names Gumtree uses in its web addresses (`london`, `manchester`, `glasgow`, `leeds`, `edinburgh`). A name Gumtree does not know makes Gumtree answer with UK-wide results; the Actor recognises that and returns an error row instead. *Extra distance* widens the area, so more listings appear, some from outside the named town; it is not a strict radius (in our test, Leeds with 5 extra miles still returned listings up to 31 miles from the centre), so use `distanceMiles` if you need a hard cut-off.
- `distanceMiles` is Gumtree's distance from the place you searched, so it is only filled when you set a location (or a link that has one). Without a location the distance Gumtree gives is not tied to your search, so the Actor leaves it empty. `imageUrl` is `null` for ads without a photo. `isUrgent` and `shippingAvailable` are `true` only on the ads that have those badges, `pricePeriod` is filled only for rents, and `condition` only in categories that ask for it (not for cars or jobs).
- `isNew` compares with what the previous run of the same search read, so it is `null` on the first run, and a listing that was beyond *Max listings per search* last time can show up as new later. Sort by *Newest first* for alerts. Promoted ads change from one request to the next, so a promoted ad can appear as new although it was posted days ago; with *Only new listings and price changes* on, the Actor leaves out promoted ads that were posted before your previous run, and *Include promoted ads* off drops promoted ads altogether. Listings the Actor has not seen for 60 days are forgotten.
- `postedAt` is the date Gumtree lists the ad with, which is not always the day the ad was first created. Some ads are "wanted" ads from buyers (for example "cash for phones"); their price is not an asking price you can buy at, so filter them out by title if you do price research.
- Public data only: what anyone sees on gumtree.com without signing in. Seller names, seller ids, phone numbers, email addresses, postcodes, map positions, vehicle registration numbers and recruiter names that Gumtree stores in its own fields are not returned. Email addresses, phone numbers in the usual UK and international formats (`07700 900123`, `7700 900123`, `+44 7700 900123`) and full UK postcodes written in capitals (`LE19 4NY`) that a seller typed into a title, a description or a detail value are removed as well (the first half of a postcode, such as `LE19`, stays). Anything else a seller wrote, such as a street address or a first name, is shown as written, so treat the text fields as the seller's own words.

Looking for German or Dutch classifieds? See [Kleinanzeigen Scraper](https://apify.com/northbell/kleinanzeigen-scraper) and [Marktplaats Scraper](https://apify.com/northbell/marktplaats-scraper).

### For AI agents

`{"searches": ["iphone 15"], "maxListingsPerSearch": 5}` returns up to 5 `listing` rows and one `summary` row. Rows have `type`: `listing`, `summary` or `error`. Only `listing` rows are charged. More than about 5 page reads per 18 minutes from one connection are slow by design (see Notes), so keep `maxListingsPerSearch` at 100 or less and use `onlyNew` for repeated runs.

# Actor input Schema

## `searches` (type: `array`):

One search per line: a keyword (iphone 15, mountain bike, sofa) or a gumtree.com search or category link copied from your browser. A link keeps its own filters and sort order (if it has none, 'Sort by' below is added); the other settings apply to keywords.

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

A UK town, city or region as it appears in gumtree.com addresses: london, manchester, glasgow, leeds, edinburgh. Empty = the whole UK. Applies to keyword searches. A name Gumtree does not know gives an error row instead of UK-wide results.

## `distance` (type: `string`):

Widen the search by this many miles beyond the location. Needs a location. Applies to keyword searches.

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

Only listings priced at or above this many pounds. Leave empty for no minimum. Applies to keyword searches. Listings without a price are kept. Gumtree applies a price limit itself only in some categories (not in Property, for example); where it does not, the Actor drops the listings outside your range after reading them, so you can get fewer rows than Max listings per search (see the Notes in the README).

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

Only listings priced at or below this many pounds. Leave empty for no maximum. Applies to keyword searches. Listings without a price are kept. Gumtree applies a price limit itself only in some categories (not in Property, for example); where it does not, the Actor drops the listings outside your range after reading them, so you can get fewer rows than Max listings per search (see the Notes in the README).

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

Limit a keyword search to one top-level Gumtree category. For a narrower category (for example Mobile Phones) open it on gumtree.com and paste the link into Searches instead.

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

Order of the results. Newest first is the right choice when you run the Actor on a schedule to catch new listings.

## `maxListingsPerSearch` (type: `integer`):

How many listings to read per search (about 25 to 30 per page, Gumtree shows at most 50 pages). Promoted ads count too. Listings the Actor drops because they are outside your price range count as read. With Only new on, this is how far down the list the Actor looks.

## `onlyNew` (type: `boolean`):

Return only listings this search has not shown before, plus listings whose price changed since the last run. The first run of a search returns everything (there is nothing to compare with yet). You pay only for the rows returned.

## `includePromoted` (type: `boolean`):

Gumtree puts a few paid 'promoted' ads at the top of every page, outside the sort order and sometimes outside the area you chose. Untick to leave them out. Promoted ads outside your price range are always left out.

## Actor input object example

```json
{
  "searches": [
    "iphone 15"
  ],
  "distance": "any",
  "category": "all",
  "sortBy": "newest",
  "maxListingsPerSearch": 100,
  "onlyNew": false,
  "includePromoted": true
}
```

# Actor output Schema

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

Gumtree listings with price, place, date, seller type and what is new or cheaper since the last run.

# 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 = {
    "searches": [
        "iphone 15"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("northbell/gumtree-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 = { "searches": ["iphone 15"] }

# Run the Actor and wait for it to finish
run = client.actor("northbell/gumtree-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 '{
  "searches": [
    "iphone 15"
  ]
}' |
apify call northbell/gumtree-scraper --silent --output-dataset

```

## MCP server setup

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