# Reed.co.uk Jobs Scraper - UK Job Listings with Salary (`rjmacarthy/reed-jobs-scraper`) Actor

Scrape UK jobs from reed.co.uk: parsed salary min/max/period, contract type, remote/hybrid, posted and closing dates, optional full descriptions and skills, and an only-new-jobs mode for job alerts. Keywords, location and filters or any Reed search URL. No login.

- **URL**: https://apify.com/rjmacarthy/reed-jobs-scraper.md
- **Developed by:** [rj](https://apify.com/rjmacarthy) (community)
- **Categories:** Jobs, Automation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 job listings

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## Reed.co.uk Jobs Scraper - UK Job Listings with Salary

Scrape public UK job listings from **reed.co.uk**, the UK's largest job board, and get clean, analysis-ready data: **salary as numbers** (min, max, period: hour, day or year), contract type, full-time/part-time, remote/hybrid/on-site, posted and closing dates, employer and, if you want them, the **full job description and Reed's skill tags**. Search by keywords, location and Reed's own filters, or paste any Reed search URL. An **"Only new jobs"** mode turns a daily schedule into a job-alert feed at no extra charge. No login, no API key, no browser.

Why this one: most Reed scrapers return the salary as a text string ("£650 - £750 per day"). UK buyers filter and benchmark by salary, so this Actor parses it into `salaryMin`, `salaryMax` and `salaryPeriod`, and it costs less than the alternatives that charge per detail page or a monitor fee.

### What data can you get?

| Field | Example |
|---|---|
| `title`, `url`, `id` | Data Analyst, https://www.reed.co.uk/jobs/data-analyst/57501240 |
| `employerName`, `employerType`, `employerUrl` | Hays Specialist Recruitment Limited, `agency` |
| `location`, `county`, `region`\*, `postcode`\* | London, London, South East England, SE1 |
| `salaryText` | £400 - £500 per day |
| `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod` | 400, 500, GBP, `day` |
| `contractType` | Permanent, Contract or Temporary |
| `workingHours` | full-time, part-time, full-time or part-time |
| `remoteType` | remote, hybrid, on-site |
| `postedAt`, `updatedAt`, `expiresAt` | ISO 8601 (UTC) |
| `isEasyApply`, `isPromoted`, `isFeatured`, `isTrainingCourse` | true / false |
| `externalApplyUrl` | Apply link when the job is applied for off Reed |
| `occupation`, `sector`\*, `parentSector`\* | Data Analyst, Analyst Prog/Dev, IT & Telecoms |
| `skills`\* | \["SQL Databases", "Power BI", ...] |
| `descriptionSnippet`, `description`\*, `descriptionHtml`\* | Short snippet; full text and HTML |
| `searchKeyword`, `searchUrl`, `scrapedAt`, `detailsStatus` | Provenance and status |

\* Needs **Include full job details** (on by default).

### Use cases

- **Salary benchmarking:** day rates for contractors, annual salaries for permanent roles, by city and job title.
- **Job-alert feeds:** schedule a daily run with **Only new jobs** and push new vacancies to Slack, email or a spreadsheet.
- **Recruitment market intelligence:** which agencies and employers are hiring, for what, and where.
- **Job aggregators and boards:** the same flat field layout as our Dice, SEEK and XING job scrapers.
- **Labour-market research:** remote vs hybrid share, contract vs permanent mix, posting volumes over time.

### How to use

1. Enter one or more **Keywords** (each one is a separate search) and a **Location**.
2. Optionally set filters: salary range, contract type, full/part-time, remote/hybrid/on-site, date posted, Easy Apply.
3. Turn **Include full job details** off for a faster, cheaper listing-only feed.
4. Run, then download the data as JSON, CSV, Excel or via the API.

Contract day-rate jobs in London posted this week, with full descriptions:

```json
{
    "keywords": ["data analyst"],
    "location": "london",
    "contractTypes": ["contract"],
    "postedWithin": "lastweek",
    "maxItems": 50,
    "includeDetails": true
}
```

Remote software engineering jobs anywhere in the UK paying £60k+ (leave the location empty):

```json
{
    "keywords": ["software engineer"],
    "remoteType": "remote",
    "salaryFrom": 60000,
    "maxItems": 100,
    "includeDetails": false
}
```

A daily job alert for nurses in Manchester (schedule it; each run outputs only jobs not seen before):

```json
{
    "keywords": ["registered nurse", "mental health nurse"],
    "location": "manchester",
    "distanceMiles": 15,
    "onlyNew": true,
    "stateKey": "nurses-manchester",
    "includeDetails": false
}
```

Or paste search URLs straight from your browser (filters in the URL are kept):

```json
{
    "startUrls": [{ "url": "https://www.reed.co.uk/jobs/accountant-jobs-in-leeds?perm=true" }],
    "maxItems": 200
}
```

### Output example

A real item (description shortened):

```json
{
  "id": "57501240",
  "url": "https://www.reed.co.uk/jobs/data-analyst/57501240",
  "title": "Data Analyst",
  "employerName": "Hays Specialist Recruitment Limited",
  "employerType": "agency",
  "employerUrl": "https://www.reed.co.uk/jobs/hays-specialist-recruitment-limited/p36210",
  "location": "London",
  "county": "London",
  "region": "South East England",
  "postcode": null,
  "salaryText": "£400 - £500 per day",
  "salaryMin": 400,
  "salaryMax": 500,
  "salaryCurrency": "GBP",
  "salaryPeriod": "day",
  "contractType": "Contract",
  "workingHours": "full-time",
  "remoteType": "remote",
  "postedAt": "2026-10-28T12:31:20.310Z",
  "updatedAt": "2026-11-01T12:32:16.690Z",
  "expiresAt": "2026-12-09T23:55:00.000Z",
  "isPromoted": false,
  "isFeatured": false,
  "isEasyApply": true,
  "isTrainingCourse": false,
  "externalApplyUrl": null,
  "occupation": "Data Analyst",
  "sector": "Analyst Prog/Dev",
  "parentSector": "IT & Telecoms",
  "skills": ["Dashboard Design & Development", "Microsoft Excel", "Power BI (Opportunity)", "SQL Databases", "Stakeholder Management (Business)"],
  "descriptionSnippet": "Data Analyst - SQL, Databricks, Sustainability up to 400pd (Inside IR35) Remote initially 6 months ...",
  "description": "Data Analyst - SQL, Databricks, Sustainability\nup to £400pd (Inside IR35)\nRemote\ninitially 6 months\n\nThe role will support ...",
  "descriptionHtml": "<p>Data Analyst - SQL, Databricks, Sustainability <br>up to £400pd (Inside IR35)<br>Remote ...",
  "detailsStatus": "ok",
  "searchKeyword": "data analyst",
  "searchUrl": "https://www.reed.co.uk/jobs/data-analyst-jobs-in-london?keywords=data+analyst&locationName=london&proximity=10&contract=true&dateCreatedOffSet=lastweek&hideTrainingJobs=true",
  "scrapedAt": "2026-11-03T10:02:21.728Z"
}
```

More items: [`samples/sample-output.json`](samples/sample-output.json). The dataset has three views: **Overview**, **Salaries** and **Details**.

### Pricing

Pay per event, no monthly fee:

| Event | Price | When |
|---|---|---|
| `job` | $0.001 | Each job listing output |
| `job-details` | $0.0005 | Each job whose detail page (full description, skills) was fetched |

- **1,000 jobs, listing data only ≈ $1.00**
- **1,000 jobs with full descriptions ≈ $1.50**
- The "Only new jobs" mode has no monitor surcharge: you pay only for the new jobs that are output.
- Set **Maximum cost per run** in the run options; the Actor stops cleanly when it is reached.
- A job whose detail page couldn't be fetched (expired, blocked) is not charged `job-details`.

### Tips and limits

- Reed shows **25 jobs per page**. For very broad searches (thousands of results), split by location or keyword and use filters to keep runs short.
- Results come in **Reed's default (relevance) order**. Sorting by date isn't offered because `sortBy` URLs are disallowed by reed.co.uk's robots.txt; use **Date posted** to narrow to recent jobs.
- **Salary filters are Reed's own**: they match on overlapping ranges, so a £55k-£65k job can appear for "from £60,000".
- When the employer hides the figure ("Salary negotiable", "Competitive salary"), `salaryText` shows that wording and `salaryMin`/`salaryMax` are `null`, as on the site.
- **Training-course adverts** (paid courses Reed lists as "trainee" jobs) are hidden by default; turn off **Hide training-course listings** to include them (`isTrainingCourse: true`).
- Times on Reed are UK local; the Actor converts them to UTC ISO timestamps.
- `detailsStatus` tells you per job whether the full description was fetched (`ok`), the job had expired (`not-found`) or the page was blocked. The run's `RUN_SUMMARY` record counts these too.
- For **Only new jobs**, use a different **State key** per alert. Seen jobs are forgotten after 90 days. **Max result pages** (default 40) caps how far an alert run pages through results it has mostly seen before.

### FAQ

**Is it legal to scrape reed.co.uk?**
This Actor collects only publicly visible job listings, without logging in, and follows reed.co.uk's robots.txt (no `/api/` or `sortBy` URLs). It does not harvest personal data: no recruiter contact fields are output, and email addresses and phone numbers inside job descriptions are replaced with `[email removed]` / `[phone removed]`. You are responsible for using the data in line with Reed's terms, UK GDPR and other laws that apply to you.

**Do I need a proxy?**
Usually not. If Reed starts answering 403/429, enable Apify Proxy (datacenter). Residential proxies are not supported: if you select the RESIDENTIAL group, the Actor logs a warning and uses Apify datacenter proxy instead.

**Can I scrape several keywords at once?**
Yes. Each keyword is a separate search with its own **Max jobs per search** limit, and a job found by more than one search is output only once per run.

**Why are some fields null?**
`region`, `postcode`, `sector`, `skills` and the full description come from the job page, so they are null when **Include full job details** is off. Some employers don't give a postcode or salary.

**What currency are salaries in?**
Reed salaries are in pounds (`salaryCurrency: "GBP"`). If a listing uses another currency, `salaryCurrency` is null and `salaryText` has no £ sign.

### Integrations

- **API:** run the Actor and fetch the dataset with the Apify API or the `apify-client` libraries for JavaScript and Python.
- **Make, Zapier, n8n:** use the Apify app/node to run the Actor on a schedule and send new jobs to Google Sheets, Airtable, Slack or email.
- **MCP:** AI agents can call this Actor through the Apify MCP server (`mcp.apify.com`).
- **Webhooks:** get notified when a run finishes and pull the new items.

### Changelog

- **0.1** (November 2026): first release. Keyword/location search with Reed filters, start URLs, parsed salaries, full job details with skills, Only-new-jobs mode.

### More scrapers by the same developer

- [ATS Jobs Scraper: Greenhouse, Lever, Ashby & Workday](https://apify.com/rjmacarthy/ats-jobs-scraper)
- [Dice Jobs Scraper](https://apify.com/rjmacarthy/dice-jobs-scraper)
- [SEEK Jobs Scraper](https://apify.com/rjmacarthy/seek-jobs-scraper)
- [Workday Jobs Scraper](https://apify.com/rjmacarthy/workday-jobs-scraper)
- [AI Visibility Tracker: ChatGPT, Perplexity, Gemini, Claude](https://apify.com/rjmacarthy/ai-search-visibility-tracker)
- [Google Ads Transparency Scraper](https://apify.com/rjmacarthy/google-ads-transparency-scraper)

Browse all my Actors on [my Apify Store profile](https://apify.com/rjmacarthy).

### Support

Found a search that doesn't work, or need an extra field? Open an issue on the **Issues** tab with your input. Fixes are usually quick.

# Actor input Schema

## `keywords` (type: `array`):

Job titles or skills to search for, e.g. "python developer" or "registered nurse". Each keyword is a separate search. Leave empty to list all jobs in the location.

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

UK town, city, county or postcode, e.g. "london", "manchester", "M1". Leave empty for the whole UK.

## `distanceMiles` (type: `integer`):

Search radius around the location. Reed offers 0, 1, 3, 5, 10, 15, 20, 30 and 50 miles; other values are rounded up.

## `salaryFrom` (type: `integer`):

Only jobs paying at least this much (Reed's own salary filter, annual figures such as 40000). 0 = any.

## `salaryTo` (type: `integer`):

Only jobs paying up to this much. 0 = any.

## `contractTypes` (type: `array`):

Permanent, contract and/or temporary jobs. Empty = all.

## `workingHours` (type: `string`):

Full-time or part-time jobs only.

## `remoteType` (type: `string`):

Remote, hybrid or on-site jobs only.

## `postedWithin` (type: `string`):

Only jobs posted within this period (Reed's date filter).

## `easyApplyOnly` (type: `boolean`):

Only jobs you can apply to directly on Reed.

## `hideTrainingCourses` (type: `boolean`):

Reed mixes paid training-course adverts ("Web Developer Trainee" etc.) into job results. On by default so you get real vacancies only.

## `startUrls` (type: `array`):

Reed search URLs copied from your browser, e.g. https://www.reed.co.uk/jobs/python-jobs-in-london?perm=true. When given, keywords, location and filters above are ignored. sortBy parameters are removed (reed.co.uk's robots.txt disallows them).

## `includeDetails` (type: `boolean`):

Open each job page for the full description (text and HTML), skills, sector, region and postcode. Charged as an extra "job-details" event per job. Turn off for a faster, cheaper listing-only feed.

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

Maximum jobs to output for each keyword or start URL. 0 = no limit.

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

Safety cap on result pages (25 jobs each) per search, mainly for "Only new jobs" runs where most jobs are skipped. 0 = no limit.

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

Skip jobs this Actor already output in earlier runs with the same state key (remembered in a named key-value store). Schedule the Actor daily for a job-alert feed. The first run outputs everything and becomes the baseline.

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

Name of the job-alert memory used by "Only new jobs". Use a different key for each separate alert/schedule.

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

Not needed normally. Enable Apify Proxy (datacenter) if reed.co.uk blocks or rate-limits the run. Residential proxies are not supported: if selected, the Actor falls back to Apify datacenter proxy.

## `maxConcurrency` (type: `integer`):

Parallel job-page requests (1-5). Keep it low to stay polite.

## Actor input object example

```json
{
  "keywords": [
    "python developer"
  ],
  "location": "london",
  "distanceMiles": 10,
  "salaryFrom": 0,
  "salaryTo": 0,
  "contractTypes": [],
  "workingHours": "any",
  "remoteType": "any",
  "postedWithin": "anytime",
  "easyApplyOnly": false,
  "hideTrainingCourses": true,
  "includeDetails": false,
  "maxItems": 10,
  "maxPages": 40,
  "onlyNew": false,
  "stateKey": "default",
  "proxyConfiguration": {
    "useApifyProxy": false
  },
  "maxConcurrency": 3
}
```

# Actor output Schema

## `jobs` (type: `string`):

One item per job: title, employer, location, salary text and parsed min/max/period, contract type, remote/hybrid and posting date.

## `jobsFull` (type: `string`):

Every field, including the full description in text and HTML, skills, sector, region and postcode.

## `summary` (type: `string`):

Per-search status, counts, request statistics and warnings.

# 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 = {
    "keywords": [
        "python developer"
    ],
    "location": "london",
    "includeDetails": false,
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("rjmacarthy/reed-jobs-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 = {
    "keywords": ["python developer"],
    "location": "london",
    "includeDetails": False,
    "maxItems": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("rjmacarthy/reed-jobs-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 '{
  "keywords": [
    "python developer"
  ],
  "location": "london",
  "includeDetails": false,
  "maxItems": 10
}' |
apify call rjmacarthy/reed-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,rjmacarthy/reed-jobs-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/p4OUUyk4uc1Opq103/builds/7Tu5zAHdd2ig3CE5q/openapi.json
