# Reed.co.uk Jobs Scraper — UK Salaries & Full Descriptions (`teodor_banea/reed-jobs-scraper`) Actor

Scrape Reed.co.uk jobs with full descriptions, normalised UK salaries (yearly figures for hourly and daily pay), town, county, region and postcode, sector, occupation, skills and employer. Filter by keyword, location, salary, job type, remote, specialism, date.

- **URL**: https://apify.com/teodor_banea/reed-jobs-scraper.md
- **Developed by:** [Banea Teodor](https://apify.com/teodor_banea) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 results

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 Salaries, Full Descriptions & Structured Locations

### What does Reed.co.uk Jobs Scraper do?

Reed.co.uk Jobs Scraper extracts job listings from [Reed.co.uk](https://www.reed.co.uk), one of the UK's largest job boards with about **100,000 live jobs**. Search by keywords, location and filters, paste Reed search URLs, or fetch specific job pages. Each row has the **full job description** (plain text and clean HTML), a **normalised salary** (amounts, pay period and Reed's yearly figure for hourly and daily rates), a **structured UK location** (town, county, region, nation, postcode district), the **occupation and sector taxonomy**, skills, contract type, working hours, remote / hybrid / on-site, the employer or agency and how to apply. No login, no browser.

### Why use this Actor?

- **Complete rows.** The full description, skills, sector and specialism, Reed's three-level occupation taxonomy, recruiter type, graduate flag, posting / update / expiry dates — not just the search card. Every row has the same 60 fields, with `null` or `[]` when Reed has no value.
- **Salaries you can compare.** Hourly, daily and yearly pay come with the pay period and Reed's yearly equivalent (`salaryYearlyMin` / `salaryYearlyMax`), plus flags for negotiable, competitive, OTE, pro-rata, commission-only and benefits. Hidden pay ("Competitive salary") is never turned into a fake number.
- **Clean, structured UK locations.** Town, county, region (e.g. "South East England"), nation (England, Scotland, Wales, Northern Ireland) and postcode district, plus remote / hybrid / on-site.
- **Filters that cost nothing.** Keywords, location and radius, salary range, job type, full / part time, remote / hybrid / on-site, posting date, specialism, agency or employer, salary shown, graduate, visa sponsorship and Easy Apply are applied by Reed's own search. You only pay for the jobs you get.
- **Beyond Reed's 10,000-result limit.** Reed shows at most 10,000 jobs per search. Larger searches (all of London, all of the UK) are split by specialism and job type automatically.
- **Nothing lost to Reed's shuffling.** Reed reorders keyword results between page loads, so reading the pages once misses a few percent of jobs. The Actor notices the gap and re-reads the result pages until every job is collected.
- **Built for scheduled feeds.** Set *Posted within* to match your schedule and every run returns the recently posted jobs of your search.

### How much does it cost?

You pay a small fee per run plus a price per 1,000 jobs returned (see the Pricing tab). Platform usage and proxy are included.

| Run | Jobs |
|---|---|
| 20 "python developer" jobs in London (the prefilled input) | 20 |
| Permanent hybrid nurse jobs from £30,000 posted in the last week | ~5–200 |
| Every job in Manchester (10 miles) | ~6,500 |
| Daily run for one keyword + location (posted in the last 3 days) | ~10–300 per day |

Turning off *Include full job details* makes runs about 6× faster and lighter (25 jobs per request instead of one).

### Input

| Field | Description | Example |
|---|---|---|
| `mode` | `search` (keywords + location + filters, default), `jobUrls` (job pages or job ids) or `searchUrls` (Reed search page URLs) | `"search"` |
| `keywords` | Keywords as in Reed's search box | `"python developer"` |
| `location` | UK town, county, region or postcode (district or full) | `"Manchester"`, `"SW1A 1AA"` |
| `distanceMiles` | Radius around the location: 0, 1, 3, 5, 10 (default), 15, 20, 30, 50 | `"20"` |
| `maxResults` | Jobs to return. 0 = all matches (capped at 10,000 without any keyword, location or filter) | `100` |
| `salaryFrom` / `salaryTo` | Yearly pay range in GBP. Reed compares its yearly figure, so hourly (× 1,950) and daily (× 260) rates match too; a job matches the minimum when the top of its range reaches it | `30000` |
| `jobTypes` | `permanent`, `contract`, `temporary` | `["permanent"]` |
| `workingHours` | `fullTime`, `partTime` | `["partTime"]` |
| `workingOption` | `any` (default), `onSite`, `hybrid`, `remote` — one at a time (Reed's search takes one) | `"hybrid"` |
| `postedWithin` | `anytime` (default), `today`, `lastthreedays`, `lastweek`, `lasttwoweeks` | `"lastweek"` |
| `specialisms` | Reed specialism ids — pick them from the list in the input form (52 = IT & Telecoms, 68 = Education, 36 = Health & Medicine…) | `["52"]` |
| `postedBy` | `any` (default), `agency`, `employer` | `"employer"` |
| `onlyWithSalary`, `graduateOnly`, `visaSponsorshipOnly`, `easyApplyOnly` | Extra filters, off by default | `true` |
| `hideTrainingCourses` | Leave out training-course adverts Reed lists among jobs (default on) | `false` |
| `jobUrls` | Job page URLs or bare job ids (jobUrls mode) | `["https://www.reed.co.uk/jobs/software-engineer/57462273", "57418395"]` |
| `searchUrls` | Reed search page URLs with any filters (searchUrls mode) | `[{"url": "https://www.reed.co.uk/jobs/nurse-jobs-in-leeds?salaryFrom=30000"}]` |
| `includeDetails` | Open every job page for the full description and details (default on). Off = lighter rows from the search results | `false` |

```json
{
    "keywords": "nurse",
    "location": "Leeds",
    "distanceMiles": "20",
    "salaryFrom": 30000,
    "jobTypes": ["permanent"],
    "postedWithin": "lastweek",
    "maxResults": 200
}
```

### Output

One row per job. Every row has every field; missing values are `null` or `[]`.

```json
{
    "jobId": "57462273",
    "title": "Software Engineer (Python and AI Solutions)",
    "url": "https://www.reed.co.uk/jobs/software-engineer-python-and-ai-solutions/57462273",
    "companyName": "University of the Built Environment",
    "companyId": "4481",
    "companyUrl": "https://www.reed.co.uk/jobs/the-college-of-estate-management/p4481",
    "companyLogoUrl": "https://resources.reed.co.uk/profileimages/logos/thumbs/Logo_4481.png",
    "postedBy": "employer",
    "recruiterType": "Charity/not for profit",
    "contractType": "permanent",
    "contractTypeText": "Permanent",
    "isFullTime": true,
    "isPartTime": false,
    "knowledgeDomain": "Information Technology",
    "professionCategory": "Engineer",
    "professionName": "Software Engineer",
    "sector": "Higher Education",
    "sectorParent": "Education",
    "skills": [],
    "isGraduate": false,
    "isTrainingJob": false,
    "isEasyApply": false,
    "applyMethod": "external",
    "eligibleUkOnly": true,
    "isFeatured": true,
    "isPromoted": true,
    "isEarlyBird": false,
    "city": "Reading",
    "state": "Berkshire",
    "region": "South East England",
    "country": "United Kingdom",
    "countryPart": "England",
    "countryCode": "GB",
    "postalCode": "RG1",
    "locationText": "Reading, Berkshire",
    "remote": "hybrid",
    "remoteText": "Hybrid",
    "salaryMin": 40000,
    "salaryMax": 45000,
    "salaryCurrency": "GBP",
    "salaryPeriod": "year",
    "salaryYearlyMin": 40000,
    "salaryYearlyMax": 45000,
    "salaryText": "£40,000 - £45,000 per annum",
    "salaryIsNegotiable": false,
    "salaryIsCompetitive": false,
    "salaryIsCommissionOnly": false,
    "salaryIsOte": false,
    "salaryIsProRata": false,
    "salaryIncludesBenefits": false,
    "summary": "Software Engineer (Python and AI Solutions) Full time (35 hrs/wk), permanent Split place of work between Horizons (Reading, Berkshire) and Home Salary range 40,000 to 45,000 pa plus benefits…",
    "description": "Software Engineer (Python and AI Solutions)\n\nFull time (35 hrs/wk), permanent\n\nSplit place of work between Horizons (Reading, Berkshire) and Home…",
    "descriptionHtml": "<p><strong>Software Engineer (Python and AI Solutions)</strong></p><p><strong>Full time (35 hrs/wk), permanent</strong></p>…",
    "postedAt": "2026-10-15T12:46:28.233Z",
    "createdAt": "2026-10-15T12:46:28.237Z",
    "updatedAt": "2026-10-19T12:47:17.277Z",
    "expiresAt": "2026-10-28T23:59:59.000Z",
    "isLive": true,
    "detailsScraped": true,
    "scrapedAt": "2026-10-20T08:00:00.000Z"
}
```

| Field | Notes |
|---|---|
| `jobId` | Reed's job id, stable across runs. Use it to deduplicate. |
| `companyName` / `companyId` / `companyUrl` | The poster: an employer or a recruitment agency (`postedBy`). Agencies do not name their client. `companyId` is the number of the poster's Reed page; posters without a Reed profile have `companyId: null`. |
| `salary*` | `salaryMin` / `salaryMax` in `salaryCurrency` (GBP for almost every job; EUR, USD, AUD or AED for some jobs abroad) per `salaryPeriod` (`hour`, `day`, `week`, `month`, `year`). `salaryYearlyMin` / `salaryYearlyMax` are Reed's yearly figures **in GBP** (hourly × 1,950, daily × 260; other currencies converted by Reed) — the numbers Reed's salary filter compares; without job details they are only filled for GBP salaries. When the employer hides the pay ("Competitive salary", "Salary negotiable", "Commission only") the amounts are `null` and the matching flag is `true`. |
| `knowledgeDomain` / `professionCategory` / `professionName` | Reed's occupation taxonomy, e.g. Information Technology › Engineer › Software Engineer. |
| `sector` / `sectorParent` | The sector the job is filed under and its Reed specialism. |
| `city` / `state` / `region` / `countryPart` / `postalCode` | Town, county, UK region, nation and postcode district. Region, nation and postcode come from the job page; the postcode district is published for about a third of jobs. |
| `remote` | `onsite`, `hybrid` or `remote`. |
| `applyMethod` | `easyApply` (one click on Reed), `reed` (Reed's application form) or `external` (the employer's site). The employer's own application link is only revealed inside Reed's application flow, which the Actor never enters. |
| `postedAt` | The date Reed shows as posted (moves when a job is re-posted); `createdAt` is the first creation. All times are UTC (Reed stores most times in UTC and those of job feeds in UK time; both are converted). |
| `detailsScraped` | `false` when *Include full job details* is off, or when a job page could not be read (the row then has the search-result fields and the job is listed in ERRORS). |

Fields that need the job page (full description, skills, sector, region, nation, postcode, recruiter type, graduate flag, apply method other than Easy Apply) are `null` / `[]` with *Include full job details* off.

#### Problems

Jobs that could not be read — expired job URLs, invalid URLs, jobs delivered without details — are listed in the run's key-value store under `ERRORS` with the public job or search page and a reason. The run's status message summarises any shortfall.

### Tips and tricks

- **Scheduling:** set *Posted within* (`postedWithin`) to match the schedule interval with a little overlap — `lastthreedays` for a daily run, `lasttwoweeks` for a weekly one — so each run only reads recently posted jobs. Rows are unique within a run; consecutive runs overlap, so drop repeats downstream by `jobId`. Reed's date filter uses the date a job was created, so a job that goes live days later can fall outside a short window; an occasional run with `anytime` catches it.
- **Large searches:** "All jobs in London" (~23,000) or the whole UK (~100,000) are split automatically. A few dozen jobs sit in a sector Reed's specialism filter cannot select, so a split search cannot reach them; the run's status says how many.
- **Remote and hybrid together:** Reed's search takes one working option at a time, so run once with `hybrid` and once with `remote` (or leave it on `any` and filter on the `remote` column).
- **Order:** keyword searches come in Reed's relevance order, location-only searches newest first. Reed offers no other sort order.
- **Speed:** with job details the Actor reads about 4–5 jobs per second (about 15,000 per hour); without them about 25–30 per second. For more than ~12,000 jobs with details, raise the run timeout above the default hour (Run options → Timeout); more memory (2 GB) makes it about 40% faster.

### Integrations

Export the dataset as JSON, CSV, Excel or XML, or connect it to Google Sheets, Slack, Zapier, Make or your own code through the Apify API and integrations. A scheduled task with *Posted within* set to match its interval turns the Actor into a daily feed of new Reed jobs (drop repeats by `jobId`).

# Changelog

This Actor's version history is a separate document: https://apify.com/teodor_banea/reed-jobs-scraper/changelog.md

# Actor input Schema

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

Choose "Search jobs" to search by keywords, location and filters, "Job URLs" for specific job pages, or "Search URLs" to page through Reed search pages you set up on the site.

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

Enter keywords as you would type them in Reed's search box (job title, skill, company), e.g. "python developer", "care assistant". Leave empty to list every job matching the location and filters.

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

Enter a UK town, county, region or postcode (district "SW1A" or full "SW1A 1AA"), e.g. "London", "Manchester", "Kent". Leave empty for the whole UK.

## `distanceMiles` (type: `string`):

Choose how far from the location jobs may be. Only used together with a location.

## `maxResults` (type: `integer`):

Enter how many jobs to return. 0 = all matching jobs (capped at 10,000 when no keyword, location or filter is set). Searches with more than 10,000 matches are split by specialism automatically, because Reed itself shows at most 10,000 jobs per search.

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

Keep jobs paying at least this much per year: Reed matches a job when the top of its pay range reaches this value. Reed compares its yearly figure, so hourly and daily rates are matched too (hourly x 1,950, daily x 260). Jobs that hide their pay ("Competitive salary") are matched on the range the employer gave Reed.

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

Keep jobs paying at most this much per year (Reed's yearly figure, as for the minimum).

## `jobTypes` (type: `array`):

Keep jobs with any of these contract types. Empty = all.

## `workingHours` (type: `array`):

Keep full-time and / or part-time jobs. Empty = all.

## `workingOption` (type: `string`):

Keep on-site, hybrid or remote jobs. Reed's search takes one value at a time: run once per option to combine them.

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

Keep jobs posted (or re-posted) in this period.

## `specialisms` (type: `array`):

Keep jobs in any of these Reed specialisms (sectors). Empty = all.

## `postedBy` (type: `string`):

Keep jobs posted by recruitment agencies, or by employers directly.

## `onlyWithSalary` (type: `boolean`):

Leave out jobs without a published salary.

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

Leave out course adverts that Reed lists among the jobs ("training jobs": for a "python" search about a third of the results). Turn off to get them too.

## `graduateOnly` (type: `boolean`):

Keep jobs Reed marks as suitable for graduates.

## `visaSponsorshipOnly` (type: `boolean`):

Keep jobs whose employer offers UK visa sponsorship (only a few dozen jobs across the UK).

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

Keep jobs that take a one-click application on Reed.

## `jobUrls` (type: `array`):

Enter Reed job page URLs (https://www.reed.co.uk/jobs/<title>/<job id>) or bare job ids, one per line. Expired jobs are listed in ERRORS.

## `searchUrls` (type: `array`):

Enter Reed job search page URLs, e.g. https://www.reed.co.uk/jobs/nurse-jobs-in-leeds?salaryFrom=30000. Set up the search on reed.co.uk and paste its address; every page of results is read. At most 10,000 jobs per URL (Reed's limit).

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

Open every job page for the full description, skills, sector, structured location (town, county, region, postcode district), recruiter type, graduate flag and Reed's exact yearly salary (one extra request per job). Turn off for lighter, faster rows from the search results: title, employer, town, county, salary, contract, working option, summary and dates stay.

## Actor input object example

```json
{
  "mode": "search",
  "keywords": "python developer",
  "location": "London",
  "distanceMiles": "10",
  "maxResults": 20,
  "salaryFrom": 30000,
  "salaryTo": 60000,
  "workingOption": "any",
  "postedWithin": "anytime",
  "postedBy": "any",
  "onlyWithSalary": false,
  "hideTrainingCourses": true,
  "graduateOnly": false,
  "visaSponsorshipOnly": false,
  "easyApplyOnly": false,
  "jobUrls": [
    "https://www.reed.co.uk/jobs/software-engineer/57462273",
    "57418395"
  ],
  "searchUrls": [
    {
      "url": "https://www.reed.co.uk/jobs/nurse-jobs-in-leeds?salaryFrom=30000"
    }
  ],
  "includeDetails": true
}
```

# Actor output Schema

## `results` (type: `string`):

Every job row of the run as JSON.

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

Title, company, location, contract, remote and salary columns.

## `resultsCsv` (type: `string`):

The same rows as a CSV download.

## `errors` (type: `string`):

Jobs that could not be read (expired jobs, invalid URLs, jobs delivered without details). Only present when something went wrong.

# 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",
    "maxResults": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("teodor_banea/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",
    "maxResults": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("teodor_banea/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",
  "maxResults": 20
}' |
apify call teodor_banea/reed-jobs-scraper --silent --output-dataset

```

## MCP server setup

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