CharityJob Scraper — UK Charity Jobs, Volunteers & Leads avatar

CharityJob Scraper — UK Charity Jobs, Volunteers & Leads

Pricing

from $1.00 / 1,000 job returneds

Go to Apify Store
CharityJob Scraper — UK Charity Jobs, Volunteers & Leads

CharityJob Scraper — UK Charity Jobs, Volunteers & Leads

$1 per 1,000 jobs, $0 to start. Scrape CharityJob.co.uk paid AND volunteer roles by keyword, location, cause, salary, workplace and date posted, then add each charity's own website, LinkedIn, HQ and open-role counts. Saved-search monitor with Slack/webhook alerts. No login, no API key.

Pricing

from $1.00 / 1,000 job returneds

Rating

0.0

(0)

Developer

Scrapers Delight

Scrapers Delight

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Share

💜 CharityJob Scraper — UK Charity Jobs, Volunteer Roles & Charity Leads

Scrape every live advert on CharityJob.co.uk — the UK's largest charity-sector job board — and get the hiring charity's own website, LinkedIn and HQ attached to each row. Paid roles and the 1,622-advert volunteer corpus, with every filter the site itself offers wired to a real input.

$1 per 1,000 jobs. $0 to start a run. No login, no API key, no cookies.


🧾 What does this Actor do?

CharityJob's search page is a two-panel UI that pre-renders the full detail of all 15 results in the same HTML response. That means one request returns 15 complete job records — full description, salary line, contract, hours, causes, tags, closing date and the charity's profile link — with no per-job fetch and no browser. This Actor walks that pagination, applies the site's own server-side filters, then optionally enriches each row twice:

  • enrichOrganisation (on by default) — fetches /organisation/<slug> for each charity and adds its own website URL, LinkedIn / Facebook / X / YouTube / Instagram / TikTok, HQ postcode, mission, about text, and how many paid and volunteer roles it currently has open. Each charity is fetched once per run, however many adverts it has in your result set — so you are never double-charged for the same organisation.
  • enrichStructuredSalary (off by default) — fetches each job page for its schema.org JobPosting block: numeric salaryMin / salaryMax / currency / period, ISO datePosted and validThrough, the employmentType enum, and every listed locality.

Add monitorMode and a schedule and it becomes a saved-search watcher that returns only adverts that are new since the previous run, with optional Slack / webhook / email alerts.


🎯 Who buys this data

BuyerWhat they do with a row
Fundraising / charity-tech vendors (CRM, donation platforms, payroll, DBS checking)A charity that is hiring a fundraiser is a charity with budget and a live pain. The row names the charity, its size band, its own website and its LinkedIn — a ready outbound record.
Charity-sector recruitment agenciesWhich charities are hiring directly right now, and which roles agencies already hold (hideAgencies, applyLabel).
Sector researchers & fundersSalary bands, cause mix, workplace mix and hiring volume across the whole UK charity sector, refreshed daily.
Volunteer-management platformsThe 1,622-advert volunteer corpus that no rival CharityJob scraper covers at all.
Job aggregatorsA clean, deduplicated feed of ~98 new paid adverts a day (measured 2026-09-05, run yrqe2Ct8glpQWnfAm: the site reported 686 paid adverts posted in the last 7 days).

📦 What you get — measured, not estimated

Every number below comes from one run on build 0.1.9, 2026-09-05: run NI8sMc1CRWmghfm1l, jobType: "both" with both enrichments on, 120 rows / 120 unique jobId (60 paid + 60 volunteer) in 140.7 seconds across 203 HTTP requests. Fill = the field is present and non-empty.

Always there, 100% of 120 rowsjobId · jobUrl · jobSlug · title · organisation · organisationSlug · organisationUrl · organisationType · partnerId · logoUrl · location · locationName · workplace · salaryRaw · causes · tags · closingDate · listedOrRefreshedOn · postedRelative · applyLabel · resultPosition · descriptionText · orgPaidJobCount · orgVolunteerJobCount · orgProfileId · sourceUrl · scrapedAt

FieldFillWhy it is not 100%
contractType99% (119/120)One advert stated no contract type
organisationSize81% (97/120)Not every charity states a staff band
postedOn61% (73/120)Refreshed adverts show "Refreshed on" instead — listedOrRefreshedOn merges the two and is 100%
hours50% (60/120)Volunteer adverts carry no hours field at all — 100% (60/60) across the paid half
refreshedOn39% (47/120)Shown only when the advert has been refreshed
shortDescription26% (31/120)A card-only field the site shows selectively
jobReference22% (26/120)Only some recruiters publish one
closingBadge10% (12/120)Shown only when a deadline is close

Booleans are always present; these are their true rates in the same 120 rows: isVolunteerRole 50% (the deliberate 60/60 split), hasOrganisationProfile 100%, activelyInterviewing 66%, isTopJob 18% (the sponsored promos — see honest limit 2), isExpiredJob 0%, isFutureJob 0%.

With enrichStructuredSalary on (same run):

FieldFillNote
datePosted, validThrough, employmentType100%ISO dates + the schema.org enum
salaryMin, salaryMax, salaryCurrency, salaryPeriod50% (60/120)Volunteer roles have no salary — 100% (60/60) across the paid half
jobRegions / jobLocalities72% / 71%Multi-site adverts list several
jobLocationType28%Only set (to TELECOMMUTE) for remote roles

With enrichOrganisation on — the lead payload (same run; all 120 rows had a charity profile page, so nothing below is diluted by missing profiles):

FieldFill
orgHeadquarters (postcode + country)78% (94/120)
orgAboutText78% (94/120)
charityWebsiteUrl68% (82/120)
linkedinUrl58% (69/120)
facebookUrl49% (59/120)
orgMission48% (57/120)
twitterUrl38% (46/120)
instagramUrl / youtubeUrl / tiktokUrl22% / 8% / 2%

⚠️ Ten columns are empty unless you turn enrichStructuredSalary on

enrichStructuredSalary ships off, because it costs an extra HTTP fetch and an extra $0.0005 charge per job. With the shipped defaults every row still carries all 62 columns, but ten of them are null on every row:

salaryMin · salaryMax · salaryCurrency · salaryPeriod · datePosted · validThrough · employmentType · jobLocationType · jobLocalities · jobRegions

Measured, defaults untouched: run 5fILHhLj0oYhBeyN9 (25 rows) and run g2i3Rtd3upc2DD1DJ (25 rows) — those ten fields were null on 50 of 50 rows. Turn the flag on and they fill (100% datePosted / validThrough / employmentType, and 100% numeric salary across paid roles, per the table above). salaryRaw is 100% filled either way and carries whatever the charity actually wrote.

The lead output shape

Set outputShape: "lead" and you get a 23-column projection of the same record — the same field names, never renamed, so both dataset views ("Overview" and "Charity leads") and any downstream mapping keep working when you switch shape:

organisation · charityWebsiteUrl · linkedinUrl · organisationType · organisationSize · orgHeadquarters · orgPaidJobCount · orgVolunteerJobCount · title · salaryRaw · salaryMin · salaryMax · contractType · hours · locationName · workplace · causes · listedOrRefreshedOn · closingDate · jobId · jobUrl · organisationUrl · scrapedAt

Verified on run 2aP61qySUDcGNCYES (build 0.1.9, 10 rows): the "Charity leads" CSV export came back with 12 of 12 columns populated and the "Overview" export with 10 of 10.


🔍 Every filter the site has, wired and tested

All of these are the site's own server-side parameters — each one was verified live on 2026-09-04 by confirming CharityJob's own result counter moved:

InputLive check on 2026-09-04
keywordsfundraising → 619 results · chief executive → 387
location + radiusmanchester r5 → 235 · r80 → 456
cause (21 values, repeatable)education + health → 501
contractType (repeatable)contract + temporary → 532
workplace (on-site / hybrid / remote)hybrid → 935 · remote → 179
minSalary / maxSalary£40k–£60k → 609
postedWithinDaysRe-measured 2026-09-05 on build 0.1.9: 3 days → 351 (iRVhHbCIbbauu1d1v) · 7 days → 686 (yrqe2Ct8glpQWnfAm) · 14 days → 1,225 (2SpeTyiXZmG1JtMKe). The 1-day bucket is calendar today, so it reads low late in the UTC day — 27 at 23:00 UTC (zekT3x2hm9N41d6wB).
sortBylatest (newest) vs closing (soonest) — different first rows
entryLevelOnly→ 143
applyNowOnly→ 525 (excludes external-ATS redirects)
hideAgencies→ 1,454 (direct charity employers only)
jobTypeRe-measured 2026-09-05 (run NI8sMc1CRWmghfm1l): paid → 1,652 · volunteer → 1,622 · both splits your cap fairly between the two (that run returned exactly 60 paid + 60 volunteer)

Plus client-side controls: excludeTopJobs, excludeExpired, maxItems, maxPages, deduplicateBy, includeDescriptionHtml, outputShape, maxConcurrency, maxRequestRetries, proxyConfiguration, and startUrls (paste any CharityJob search or single job URL — the URL's own querystring wins, the fields above are merged in only where it is silent).


💵 Pricing

Pay per event. There is no charge to start a run, and both of Apify's auto-events are removed.

EventPriceWhen it fires
Job returned$0.001 ($1 per 1,000)Once per advert delivered to your dataset. Rows dropped by your filters, by deduplication, or by the monitor's seen-set are never charged.
Charity profile enriched$0.0005Once per unique charity profile fetched. A charity with ten adverts costs one charge, not ten.
Structured salary fetched$0.0005Per job page fetched for numeric salary + ISO dates. Opt-in, off by default.
Monitoring run$0.01Once per scheduled monitor run.
New advert detected$0.002Per advert that is new since the previous monitor run.

What a full scrape costs you today. The site reported 1,652 live paid adverts on 2026-09-05 (run NI8sMc1CRWmghfm1l). Rival prices below were read from the Apify store API the same day, not from memory:

Rate1,652 paid adverts
This Actor$0.001/row, no start charge$1.65
memo23/charityjob-scraper$0.0015/row + $0.05 start$2.53
getdataforme/charityjob-urls-scraper$0.009/row + $0.05 start$14.92

Charity enrichment adds $0.0005 per unique charity, not per row. Measured on the 120-row run above: 75 unique charities behind 120 rows → +$0.0375 (charged 75, verified against 75 distinct organisationSlug values). Over a whole-corpus scrape the worst case is one unique charity per row, so an all-1,652 enriched scrape is $1.65 + at most $0.83.

What maxTotalChargeUsd actually does here. Before anything is written, the run prices every row it is holding against the budget you set — the row itself plus the charity-profile and structured-salary events that row will owe — and delivers only the rows the budget can pay for in full. A row that cannot be paid for completely is withheld, not shipped, so you never pay an enrichment charge for a row you did not receive, and the run total never crosses your cap. Measured 2026-09-05 on build 0.1.9: at a $0.0100 cap with both enrichments on (run JQTpnBgabykQAzAah) the run stored 5 rows and billed 5 rows + 4 charity profiles + 5 salary fetches = $0.0095; at a $0.0200 cap with charity enrichment on (run N1fBkYE01Ra1gkCnA) it stored 14 rows and billed 14 rows + 12 profiles = $0.0200 exactly. Rows stored equals rows billed on both, and both numbers reproduced exactly on the shipped build (runs ia03DJsdRGwXvCd3Z and 02tgk8WO2gYcfTkDt). (On build 0.1.8 the same $0.0100 cap billed $0.0105 — over the cap — and asked to charge 17 profiles and 20 salary fetches behind 10 delivered rows; run kZrf2EPW56a8H6OcX. That is fixed.)


🧪 Reliability, measured

  • Transport: plain HTTP + cheerio through an Apify datacenter proxy. The escalation ladder (direct / datacenter / residential-GB) returned byte-identical 570,104-byte responses on the 2026-09-04 transport probe, so the cheapest rung is the default. No browser, no residential, 512 MB. Every run listed on this page went through that default datacenter proxy and returned 200s with zero blocks.
  • Sustained load (2026-09-04 probe, single attempt, no retry, all through an Apify proxy): datacenter sequential 39/40 (97.5%), concurrency 5 → 10/10, concurrency 10 → 19/20. Across 90 proxied requests CharityJob returned zero 403, zero 429, zero CAPTCHA, zero soft-block — both failures were Apify-proxy-side 595 ECONNRESET, which the default 3 retries (each on a fresh exit IP) absorb entirely.
  • Speed (re-measured 2026-09-05 on build 0.1.9): 120 rows with both enrichments — 8 listing pages + 75 charity profiles + 120 job pages = 203 HTTP requests — in 140.7 seconds (run NI8sMc1CRWmghfm1l). Unenriched is far faster: 25 rows with charity enrichment only in 8.1 s (5fILHhLj0oYhBeyN9), and a 2-row counter probe in 6.3 s (NAUMgCJDav9hZr7nb).
  • Pagination is bounded and self-describing: the page reports its own total and page count, and the crawl stops at the last page. 15 results per page is fixed by the site (?pagesize=100 is ignored).

⚠️ Honest limits — read these before you buy

  1. There is no apply link, and this Actor does not invent one. CharityJob's apply button is a JavaScript-only trigger through track.charityjob.co.uk; no destination URL exists anywhere in the page HTML. What you get instead is applyLabel"Apply Now" (apply on CharityJob) or "Redirect to recruiter" (external ATS) — which is honest and 100% filled.
  2. Sponsored "Top job" promos are injected into EVERY result set, regardless of your filters. Measured: advert 1082124, located "Remote", appeared under both cause=education and location=london. That is the site's behaviour, not a bug in the filter. Set excludeTopJobs: true to drop them (they were 18% — 22 of the 120 rows in run NI8sMc1CRWmghfm1l).
  3. A salary filter silently drops adverts with no stated salary. That is how the site works.
  4. orgHeadquarters is a postcode + country, read from the charity's own map embed — not a full street address.
  5. Some charities have no CharityJob profile page. Their name still comes through; hasOrganisationProfile is false and the enrichment fields stay null. Across the 170 rows I measured on 2026-09-05 (runs NI8sMc1CRWmghfm1l, 5fILHhLj0oYhBeyN9, g2i3Rtd3upc2DD1DJ) every single row did have a profile — so check hasOrganisationProfile rather than assuming a rate.
  6. Ten columns are null unless you opt in. With the shipped defaults enrichStructuredSalary is off, and salaryMin, salaryMax, salaryCurrency, salaryPeriod, datePosted, validThrough, employmentType, jobLocationType, jobLocalities and jobRegions are null on every row (measured: 50 of 50 rows across runs 5fILHhLj0oYhBeyN9 and g2i3Rtd3upc2DD1DJ). They are opt-in because each one costs an extra fetch and an extra $0.0005 per job. salaryRaw is 100% filled either way.
  7. This corpus is modest and it churns. 1,652 paid + 1,622 volunteer adverts live on 2026-09-05 (run NI8sMc1CRWmghfm1l), with 686 paid adverts posted in the previous 7 days (~98/day, run yrqe2Ct8glpQWnfAm) — so the whole live paid corpus turns over in roughly 17 days. The counter also moves while you read it: the same paid search reported 1,659 eight minutes earlier the same evening (run g2i3Rtd3upc2DD1DJ). If you want a one-off list, it is a small one; the value is in watching the flow.
  8. refreshedOn vs postedOn are mutually exclusive on the site. Use listedOrRefreshedOn, which merges them and is 100% filled (postedOn alone was 61% — 73 of 120 — and refreshedOn 39% — 47 of 120 — in run NI8sMc1CRWmghfm1l).

❓ FAQ

Do I need a CharityJob account or an API key? No. Everything this Actor reads is a public, server-rendered page.

Does it work without a proxy? It runs, but use the default Apify proxy. Datacenter is measured sufficient — residential is not required, though you can pin apifyProxyGroups: ["RESIDENTIAL"], countryCode: "GB" if you prefer.

How many jobs are there in total? The site reported 1,652 paid and 1,622 volunteer adverts on 2026-09-05 (run NI8sMc1CRWmghfm1l). The Actor reads the live figure from the page and logs it every run, so you always know the size of your query before you commit to it.

Can I scrape the whole site? Yes — set maxItems: 0 and jobType: "both". On 2026-09-05 that was 3,274 rows, $3.27 unenriched (1,652 + 1,622, run NI8sMc1CRWmghfm1l).

How do I get only new jobs? monitorMode: true on a schedule. The seen-set lives in a named key-value store so it survives between runs. Verified 2026-09-05 on build 0.1.9: round 1 (ueZLsTzyegaJsyr26) returned 10 new of 10 and charged job-scraped: 10, new-job-detected: 10, monitor-run-completed: 1; round 2 over the identical search a minute later (fSs1lDG9XasfEmi0p) returned 1 new of 10 — one genuinely fresh advert had been listed in between — and charged 1 row, 1 new-job-detected and the one monitor-run-completed. The nine already-seen adverts were suppressed and cost nothing. Pair it with postedWithinDays: 1 to keep runs tiny.

Will I be charged twice for the same job? No. deduplicateBy: "jobId" is the default and it collapses the sponsored promos that repeat across pages. A/B verified 2026-09-05 with the same search URL listed twice in startUrls, maxItems 30: with the default "jobId" (run cZajAeBeLeehAXwIc, build 0.1.9) → 30 rows, 30 unique, max repeat 1, and the crawler simply pages on to fill the cap with genuinely new adverts; with "none" (run ead3ode2CCsmJNAJj) → 30 rows but only 15 unique, every id twice, billed 30. The control double-charges; the shipped default does not.

Will I be charged twice for the same charity? No. Organisation enrichment deduplicates by organisationSlug. Verified on run NI8sMc1CRWmghfm1l: 120 rows contained 75 distinct organisationSlug values, 75 profiles were fetched, and chargedEventCounts shows organisation-enriched: 75 — not 120.

What if my search returns nothing? The run exits cleanly with zero rows and charges nothing. The Actor distinguishes a genuinely empty search (the site's counter reads 0) from a broken parse (the counter is missing, or says >0 while no rows parsed) — the latter fails the run loudly rather than handing you a silently empty dataset.

Can I paste a URL from my browser? Yes. Put any charityjob.co.uk/jobs?… or /volunteer-jobs?… search URL in startUrls and its querystring becomes the filter set. A single job URL works too and returns that one advert.

What's the difference between full and lead output? full is every field — 62 columns with the shipped defaults. Counted on every row of runs 5fILHhLj0oYhBeyN9 (25 rows), g2i3Rtd3upc2DD1DJ (25) and NI8sMc1CRWmghfm1l (120): exactly 62 keys, no row short. Two options each append one more column — includeDescriptionHtml adds descriptionHtml, and monitorMode adds isNew (measured on run ueZLsTzyegaJsyr26: the 62-column full shape came back with 63, isNew present on all 10 rows). lead is a 23-column projection of those same fields, under the same names — organisation, charityWebsiteUrl, linkedinUrl, type, size, orgHeadquarters, open-role counts, title, salary, locationName, workplace, causes, closingDate and the URLs. Because the names do not change, both dataset views work in either shape. Note: two of those 23 — salaryMin and salaryMax — are part of the opt-in set in honest limit 6, so with the shipped defaults they arrive empty in the lead shape too (measured on run 2aP61qySUDcGNCYES: 23 columns, salaryMin/salaryMax 0 of 10, every other column 4–10 of 10). Turn enrichStructuredSalary on if your CRM needs numeric pay.

Does it cover volunteer roles? Yes — /volunteer-jobs is the site's own second tab over the same search grammar, 1,622 adverts, parsed by the same code into the same fields. Set jobType to volunteer or both.

Why is salaryMin empty? Most often because enrichStructuredSalary is off by default — with the shipped defaults salaryMin and nine sibling columns are null on every row (see honest limit 6). Turn it on and it filled 100% of paid rows (60/60) in run NI8sMc1CRWmghfm1l. It stays empty on volunteer adverts (no salary exists) and on adverts that state pay only as free text. salaryRaw is 100% filled either way and carries whatever the charity actually wrote.


CharityJob's robots.txt (fetched 2026-09-04) opens with, verbatim:

User-agent: *
Allow: /

and disallows only /feeds/, /Invoice/ and /attachments/none of which this Actor requests. /jobs, /volunteer-jobs and /organisation are explicitly allowed and are listed in the site's own jobsitemap.xml. The file additionally names a list of AI/SEO crawlers (Bytespider, GPTBot, Diffbot, Amazonbot, ClaudeBot, CCBot, PerplexityBot and others) as blocked or crawl-delayed; this Actor is none of them and does not impersonate them.

This Actor reads only ordinary public pages. It does not log in, does not solve CAPTCHAs, does not forge authentication, and does not fire the site's tracked apply endpoint.

Job adverts can contain personal information (named hiring contacts inside a description). You are the data controller for anything you collect, and you are responsible for complying with CharityJob's Terms of Service, UK GDPR, and any applicable marketing rules (PECR) before contacting anyone. Use the data for market research, lead generation and job aggregation — not for unsolicited bulk email to named individuals.


Built by ScrapersDelight. Not affiliated with, endorsed by, or connected to CharityJob or CharityJob Ltd.