NHS Jobs Scraper — Vacancies & Recruiter Contacts avatar

NHS Jobs Scraper — Vacancies & Recruiter Contacts

Pricing

from $0.80 / 1,000 per job returneds

Go to Apify Store
NHS Jobs Scraper — Vacancies & Recruiter Contacts

NHS Jobs Scraper — Vacancies & Recruiter Contacts

Scrape jobs.nhs.uk: every live NHS and private-healthcare vacancy with band, pay scheme, salary, contract type, employer address & website — plus the recruiter contact block (name, job title, email, phone) that 9 in 10 adverts publish. Filter by band, staff group, locum/bank, location & date.

Pricing

from $0.80 / 1,000 per job returneds

Rating

0.0

(0)

Developer

Scrapers Delight

Scrapers Delight

Maintained by Community

Actor stats

0

Bookmarked

3

Total users

2

Monthly active users

7 days ago

Last modified

Share

🏥 NHS Jobs Scraper — vacancies and the recruiter you can actually email

Scrape jobs.nhs.uk, the UK's official NHS Jobs board, into a clean table: every live vacancy with its employer, location, salary, Agenda-for-Change band, contract type and closing date — plus the contact block every advert publishes: a named person, their job title, their work email and often a direct phone number.

That last part is the difference. Most job scrapers give you a posting. This one gives you a person at a healthcare employer, with a role and a live budget.

Measured on 2026-09-04: 11,613 live adverts across 1,162 pages. In one 24-hour window the board took 1,182 new adverts from 370 distinct employers — 705 of them NHS trusts, boards and ICBs, 477 private healthcare groups, hospices, care-home operators and GP practices. This Actor pulled that entire day's intake in 74 seconds.


⚡ What you get per advert

From the search card (100% fill, measured on 100 adverts):

  • 🆔 advertReference — the stable NHS Jobs reference (e.g. C9426-26-0318), used for deduplication
  • 💼 jobTitle, employerName, locationText (town + postcode)
  • 💷 salaryText plus parsed salaryMin / salaryMax / salaryPeriod / salaryMinPerAnnum
  • 📄 contractType (Permanent · Fixed-Term · Locum · Bank · Secondment · Apprenticeship · …)
  • 🕒 workingPattern (full time, part time, remote, compressed hours, job share, …)
  • 📅 datePosted and closingDate as ISO dates, plus daysUntilClosing
  • 🔗 jobUrl

From the advert page (one extra request, scrapeJobDetails):

  • 👤 contactName · contactJobTitle · contactEmail · contactPhone — the recruiting manager
  • 🏥 employerLooksNhs + employerNhsSignal — tells an NHS body apart from a private provider or GP practice, and tells you which signal decided it (name or website)
  • 🎚️ band and payScheme (Agenda for change · Hospital medical and dental staff · Other)
  • 🏢 employerAddressLine1/2, employerTown, employerCounty, employerPostcode, employerCountry
  • 🌐 employerWebsite + employerWebsiteDomain — the domain you can enrich against
  • 📋 personSpecification grouped by category, plus flat essentialCriteria / desirableCriteria
  • 📝 jobOverview, jobDescription, jobResponsibilities, aboutOrganisation
  • dbsCheckRequired, ukRegistrationRequired, sponsorshipStatementPresent
  • 📎 supportingDocuments, accreditations, applyUrl, tracJobReference

🎯 Who buys this

BuyerWhat the row is worth
Locum & bank staffing agenciesFilter contractType = Locum, Bank and email the named ward manager or rota lead directly — 114 locum/bank adverts landed in a single 24-hour window
Permanent healthcare recruiters872 permanent roles a day, each with the hiring manager's own address
Medical device, clinical software & training vendorsThe advert names the department head — Oncology Matron, Head of Audiology, Consultant Clinical Scientist — and the trust's website domain
Workforce & pay analystsBand, pay scheme and parsed salary across the whole live market, refreshed daily
Care-home & private-provider suppliers40% of adverts are Barchester, Avery, Cygnet, Elysium, HCRG, Agincare and independent GP practices — not NHS bodies at all

📊 Measured field fill

Two real runs through this Actor on 2026-09-04, details on. No estimates.

Sample A — the 100 newest adverts on the board (representative of the daily flow):

FieldFillFieldFill
all 9 search-card fields100%tracJobReference78%
contactName100%applyUrl78%
contactEmail99%desirableCriteria46%
contactJobTitle91%supportingDocuments38%
contactIsNamedIndividual → true93 of 100contactPhone32%
payScheme100%accreditations30%
employerWebsite / Town / Postcode100%band27%
jobOverview / jobDescription / jobResponsibilities / aboutOrganisation100%employerCounty21%
personSpecification / essentialCriteria100%contractDuration13%
salaryMin / salaryMax (parsed)87%employerLogoUrl0% — see limits

Sample B — 90 adverts stratified across three unrelated filters (estates + admin · consultant + specialty doctor · bank + locum), to check the numbers hold away from the newest slice: band 46%, contactPhone 47%, contactJobTitle 91%, named individual 87 of 90, every search-card field and every contact email still 100%.


🧭 Honest limits — read these before you buy

  • This is not "NHS trusts only". Across a full day's 1,182 adverts, 705 were NHS bodies and 477 were not — private hospital groups, care-home operators, hospices, GP practices and Primary Care Networks all advertise here. employerLooksNhs marks the difference. It fires on either the employer name (nhs / trust / health board / ICB / CCG / HSCNI, and the Welsh equivalents) or the employer's own website domain (*.nhs.uk, *.nhs.wales, *.nhs.scot, *.hscni.net), and employerNhsSignal records which one. The domain test matters: trusts advertise under short trading names, so "Leeds Teaching Hospitals" (leedsth.nhs.uk) and "SECamb" (secamb.nhs.uk — South East Coast Ambulance Service) carry no "NHS" and no "Trust" in the name at all. Measured on 62 distinct employers across the 120 newest adverts: every classification agreed with a by-hand reading. Two judgement calls are yours to make, and employerNhsSignal is what lets you make them: GP practices and NHS-commissioned CICs (Locala, Your Healthcare CIC, GP federations) count as not NHS unless they publish on an NHS domain, and independent charity hospices (Marie Curie, St Giles Hospice) count as not NHS. Filter on employerNhsSignal === 'name' if you want trusts and boards only.
  • The contact email domain is deliberately not used to decide this. nhs.net mailboxes are issued to NHS-commissioned GP surgeries and private providers too — in a 60-row sample, 5 of the 6 nhs.net senders were GP surgeries or a private care group — so treating it as an NHS signal would over-claim.
  • band is only ~27–46% filled, and that is the site, not the scraper. Only employers on Agenda for Change publish a band; a care-home group posting an hourly rate has none.
  • employer is a fuzzy word match, not an exact employer filter. Searching Guys and St Thomas NHS Foundation Trust returns 5,118 of 11,612 adverts because it matches any of those words. Use one distinctive word and filter the output.
  • employerLogoUrl is almost always empty. NHS Jobs inlines employer logos as base64 data: URIs, which would add tens of KB to every row, so only a real hosted URL is emitted. employerHasLogo tells you whether a logo exists at all.
  • applyUrl is jobs.nhs.uk's own apply redirect, not the employer's ATS vendor URL.
  • contactPhone is present on about a third of adverts, not all of them.
  • Welsh mode (language: cy) changes the labels, not the corpus — the same 11,613 adverts, with employer-written text served in Welsh where the employer wrote it in Welsh.
  • The site 403s datacenter IPs. Measured: Apify datacenter proxies pass 60% first try and 87% even with four retries; Apify RESIDENTIAL, country GB passes 100% (25/25 sustained, 50/50 at concurrency 20). Keep the default proxy setting.

💰 Pricing

Pay per event. No monthly rental, no platform-usage surcharge, no charge for a run that returns nothing.

EventPriceWhen it fires
Per job returned$0.0008Once per advert delivered to your dataset
Per job detail enriched$0.002Only when detail fetching is on and the advert page actually returned data
  • A listing-only crawl of 1,000 adverts costs $0.80.
  • A fully enriched crawl with recruiter contacts — 1,000 adverts costs $2.80.
  • A daily delta (everything posted in the last 24h, ~1,180 adverts, fully enriched) is about $3.30 a day.
  • A weekly full sweep of all 11,613 live adverts, fully enriched, is about $32.50.

Nothing is charged for: duplicate advert references (collapsed before billing), adverts your posted/closing window dropped, a detail fetch that failed, or a run that found no adverts.


🚀 Quick starts

A staffing agency's daily locum feed

{
"contractType": ["Locum", "Bank"],
"sort": "publicationDateDesc",
"postedWithinDays": 1,
"scrapeJobDetails": true,
"outputFormat": "lead",
"maxItems": 0
}

Everything closing in the next 3 days (fill-rate outreach)

{
"sort": "closingDate",
"closingWithinDays": 3,
"staffGroup": ["NURSING_AND_MIDWIFERY_REGD", "ALLIED_HEALTH_PROF"],
"outputFormat": "lead"
}

Senior decision-makers at NHS trusts (a vendor's target list)

{
"payBand": ["BAND_8B", "BAND_8C", "BAND_8D", "BAND_9", "VERY_SENIOR_MANAGER"],
"scrapeJobDetails": true,
"outputFormat": "lead",
"maxItems": 0
}

Paste a search you built on the site

{
"startUrls": [
{ "url": "https://www.jobs.nhs.uk/candidate/search/results?keyword=radiographer&location=Leeds&distance=30" }
],
"maxItems": 200
}

⚙️ Every input, and what it really does

InputNotes
startUrlsSearch-results URLs or single /candidate/jobadvert/REF URLs. When non-empty these ARE the search and the filter fields below are ignored (row-level options still apply).
keywordThe site's free-text "What?" box.
location + distanceTown, city, county or postcode; radius 5 / 10 / 20 / 30 / 50 / 100 miles. Measured: Leeds alone = 201 adverts, Leeds + 100 miles = 4,421. Radius without a location is ignored — by the site, so by this Actor too.
employerFuzzy word match. See Honest limits.
jobReferenceExactly one advert.
payBand18 values, Band 2 → Band 9 plus the medical grades. Verified additive: Band 7 (850) + Band 8a (397) = 1,247.
staffGroupThe 9 NHS occupational groups. Verified additive: 2,490 + 1,911 = 4,401.
contractTypePermanent · Fixed-Term · Locum · Bank · Secondment · Apprenticeship · Voluntary · Training · Honorary · NHS Reservist. Verified additive: Locum (187) + Bank (1,125) = 1,312.
workingPatternIncludes remote-working — 128 live remote adverts when measured.
payRange, salaryFrom, salaryToBanded and exact salary filters, both server-side and independent of each other.
sortBest match · newest · closing soonest · salary high/low.
postedWithinDaysThe delta lever. The site has no date filter, so the Actor sorts newest-first and stops the moment a whole page leaves your window — measured: a 24h window read 136 of 1,162 pages, not all of them.
closingWithinDaysKeeps adverts closing within N days and drops already-closed ones.
maxItems, maxPagesPerSearchYour cost controls. maxItems: 0 = the whole result set.
scrapeJobDetailsThe second request per advert — the whole contact/band/person-spec block.
includeContactDetailsIndependent switch for the four personal-data fields.
includeFullDescriptionAdds the three long text blocks. Off by default (rows stay ~2 KB instead of ~8 KB).
includeCriteriaAdds the person specification.
outputFormatfull · lead (29 CRM-ready columns) · minimal (10 columns).
deduplicateByReferenceOn: one row per advert for the whole run. Off: one row per (search, advert) with sourceSearchUrl — and each copy is billed. Page overlap inside one search is collapsed either way.
languageen / cy.
covidJobsOnlyThe site's legacy flag. Still works, still tiny (9 adverts).
proxyConfigurationDefaults to Apify Proxy RESIDENTIAL, country GB.
tryDatacenterFirstTries the cheap datacenter rung first, falls back to residential on a block. Measured across real runs: roughly half of all requests are served by the cheap rung, halving residential bandwidth. Skipped automatically when you bring your own proxy.
maxConcurrency, maxRequestRetriesMeasured clean at 20 parallel; 10 is the polite default.

Deliberately NOT exposed, because they are measured no-ops on this site and would be fake levers: country= (returns the unfiltered 11,612), internalOnly / externalOnly (same), and employerCode (returns 0 rows without an internal code list nobody outside NHS Jobs has).


❓ FAQ

Does this need an NHS Jobs login or API key? No. Every page this Actor reads is a public page any visitor can open. NHS Jobs does run a partner API at api.jobs.nhs.uk, which is key-gated and returns 403 — this Actor never touches it, because using it would mean forging credentials.

Is every employer an NHS trust? No, and that surprises people. Over a full day's intake, 705 of 1,182 adverts came from NHS bodies and 477 from private healthcare groups, hospices, care-home operators and GP practices. Use employerLooksNhs to split them, and employerNhsSignal to see whether the employer name or the employer's NHS website domain is what decided it.

How fresh is the data? NHS Jobs takes roughly 1,000–1,200 new adverts a day, so the ~11,600-advert corpus turns over about every 11 days. Schedule this Actor daily with postedWithinDays: 1 and you have the whole market.

Why is band blank on so many rows? Because the employer isn't on Agenda for Change. Care-home groups and private providers post an hourly or annual rate with no band. That is the source data, not a parsing gap.

Can I get an exact single employer? Not from the site's employer box, which matches any word you type. Search a distinctive word (Barchester, Barts) and filter employerName in your own pipeline, or paste a start URL.

How many results can one run return? The whole result set. Pagination is lossless — verified to the last page of a 495-page result set, which returns its final two rows before page 496 returns zero. A 136-page contiguous crawl returned 1,182 rows with zero duplicates.

Will it break my budget? No. maxItems hard-caps the run, and the Actor also clamps itself to whatever your maxTotalChargeUsd can actually pay for before it starts crawling.

What happens if the site blocks the run? It exits cleanly with a status message explaining that it was a transport block, not an empty result — and charges nothing. It only fails loudly if NHS Jobs answers 200 with something that isn't a results page, which would mean the markup changed and the output could be silently wrong.

Does it work with the Welsh site? Yes — set language: "cy". Dates, pagination and every field are parsed in both languages.

Can I export to CSV / Google Sheets / my CRM? Yes. Use outputFormat: "lead" for a 29-column CRM-ready sheet, then Apify's standard CSV, JSON, Excel or API export, or a webhook straight into your stack.


  • This Actor reads public pages on jobs.nhs.uk as an ordinary visitor. It uses no login, solves no CAPTCHA, forges no credentials, and touches no anti-abuse control. jobs.nhs.uk/robots.txt does not exist — the path serves the site's generic HTML page and carries zero directives.
  • The contact fields are personal data under UK GDPR. They are names, work email addresses and sometimes direct or mobile numbers of real people. Employers publish them so candidates can ask about that specific vacancy. Contacting someone about the role they advertised sits close to that original purpose; using the same details for unrelated marketing repurposes them and puts a lawful-basis, transparency and opt-out obligation on you, the user of this Actor, not on Apify and not on us. includeContactDetails: false removes those four fields entirely if you would rather not hold them.
  • You are responsible for complying with the NHS Jobs terms of use and with applicable data protection law in your jurisdiction. This Actor gives you access to published information; how you use it is your decision and your liability.
  • Not affiliated with, endorsed by, or connected to NHS England, NHS Jobs, or any NHS organisation.