CV-Library Scraper [$1/1K💰] | UK Jobs | Salary Data
Pricing
from $0.90 / 1,000 results
CV-Library Scraper [$1/1K💰] | UK Jobs | Salary Data
Scrape UK job listings from cv-library.co.uk: titles, companies, locations + geo-coordinates, parsed salaries, contract types, dates, full descriptions and apply URLs (up to 10,000 jobs/run). Automatic Cloudflare warm-up. Pay-per-event.
Pricing
from $0.90 / 1,000 results
Rating
0.0
(0)
Developer
Ahmed Jasarevic
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Cv Library Co Uk Scraper
Scrape UK job listings from cv-library.co.uk (one of the UK's largest job boards) as clean structured JSON: job title, company + advertiser type, location with geo-coordinates, parsed salary (min/max/period), contract type, posted date, description and apply URL. Up to 10,000 jobs per run. Built for UK recruiters, staffing agencies, salary-benchmarking tools and labour-market researchers who need CV Library job data without an API key.
A plain-HTTP CheerioCrawler (no browser for the crawl) that reads the search backend records the site embeds in its pages as Next.js flight data, with an automatic UK-residential warm-up that solves the Cloudflare challenge.
Main Use Cases
- UK job market data and salary benchmarking - parsed
salaryMin/salaryMax/salaryPeriodacross keywords, locations and distances - Recruitment lead generation - companies, advertiser type (Recruitment Agency vs Direct Employer), locations and geo centroids
- Job board and job feed APIs - up to 10,000 jobs per run as clean JSON rows
- Hiring trend tracking - scheduled runs diffing
postedDateISOandexpiryDateacross the UK - Candidate sourcing and market analysis - city/region/postcode/country plus industry and contract type per role
How It Works - The Bypass
CheerioCrawler (plain HTTP, no browser) with a single-stage crawl by default:
- Search pages (
https://www.cv-library.co.uk/<keywords>-jobs[-in-<location>], 100 results per page, paginated via?page_number=N) - the primary structured source is the site's own search-backend records embedded in the page as Next.js flight data (self.__next_f.push(...)scripts carrying{"data": {"meta": {total, limit, offset}, "results": [...]}}). Each record carries id, title, fullaccount(id, name, type - exactly "Recruitment Agency"/"Direct Employer"),location(name, city, county, postcode-style display,centroidlat/lon),salary({currency, period, min, max}),contract, ISOposteddate,category,flags(featured),logo, apply URLs and the description (HTML). No DOM scraping needed for any of these - 100 jobs per request. - Job detail pages (
/job/{id}/{slug}, optional withincludeDescription: true) - add the full description, expiry date, contract length and direct-apply flag from theapplication/ld+jsonJobPosting block, with stabledata-qahooks as fallback. This costs one request per job, is paced (maxConcurrency: 1, ~1.2 s between requests) and is off by default because the site's WAF rate-limits datacenter IPs. If a detail page fails, the backend record is still pushed, so no listing is ever lost.
Why The Egress IP Matters (verified)
cv-library.co.uk sits behind a Cloudflare WAF that returns HTTP 403 with a large block page for unfamiliar IPs and request bursts. Verified tests on the same day:
- Node.js + got-scraping (Chrome-shaped TLS via the UA's ciphers/curves, HTTP/2) -> 403.
impitwith a genuine Chrome TLS/HTTP2/QUIC fingerprint (JA3/JA4, header order) -> still 403. A real Chrome handshake from a datacenter IP is enough to fail the WAF; a perfect fingerprint on a blacklisted IP does not help.- UK residential IPs -> 0 x 403, ~7 s for a 10-job run.
So the fingerprint is already as good as it gets for free; the only lever that removes the 403s is the egress IP plus a real browser warm-up. This actor bakes that in automatically: at run start a real Chromium is launched once through a UK residential sticky session (real Chrome UA + TLS), which solves the Cloudflare challenge and "warms" that exit IP; then the CheerioCrawler scrapes fast on the same IP + User-Agent (cf_clearance is bound to the IP + UA pair, so both are reused). Tested: 0 x 403, 60 jobs in ~7 s, versus 403 on every direct/datacenter request. Residential traffic is billed through Apify's normal residential proxy accounting (~$8 per GB - a list-mode run is only a few MB). A 1,000-job detail-mode run needs ~20 minutes and is the most likely mode to hit 403s (fail-safe: falls back to the list-level record, never loses a listing).
There is no user-facing proxy or anti-block input - the hybrid residential mode is fixed and automatic in the current version.
Which Bypass Was Used, And Why
| Candidate surface | Verdict |
|---|---|
Official search-jobs-json / partner Job View API | Not usable - requires a partner API key (key=KEY, 400 without it); documented at cv-library.co.uk/developers but not available without approval |
| Algolia / Meilisearch / other third-party search backend | None found - first-party search index queried as /jobs?class=!organic&facet=...&keyword=...&limit=..., Cloudflare-walled for direct calls |
| Embedded Next.js flight data with full backend records | Used (default) - same records the /jobs backend returns, with salary/geo/company/posted/description, parsed server-side, no browser, no DOM scraping |
Embedded application/ld+json JobPosting | Optional (includeDescription: true) - adds full description HTML, validThrough expiry, employmentType, contract length |
| Static search HTML via CheerioCrawler | Used as transport + fallback (DOM cards only if flight data is ever absent) |
| Playwright / browser rendering | Not needed for the crawl - all target fields exist in served HTML/embedded JSON (the browser is used only for the one-shot Cloudflare warm-up) |
Input Parameters
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
searchQuery | string | No | software developer | Job title, keywords or skills; empty = browse all jobs |
keywords | array | No | [] | Optional list of queries; each runs its own search and shares the maxResults budget |
location | string | No | empty | City, town, postcode or county, e.g. London, M1 1AA, West Yorkshire |
distance | integer | No | 15 | Search radius in miles (0-750); only applies when a location is set |
contractType | string | No | any | any / permanent / contract / temporary / part-time / apprenticeship |
daysOld | integer | No | 14 | Only listings posted within this many days; CV-Library supports 1 / 3 / 7 / 14-day bands, other values round up |
salaryMin | integer | No | 20000 | Minimum annual salary, GBP |
salaryMax | integer | No | 100000 | Maximum annual salary, GBP |
startUrls | array | No | [] | CV-Library search-result or job URLs to scrape directly instead of building a search |
maxResults | integer | No | 100 | Max jobs to return (1-10000); free users get a 10-job preview |
maxPages | integer | No | 50 | Max search pages per search (1-500, 100 jobs per page) |
includeDescription | boolean | No | false | OFF (default): list-level data only - 1 request per 100 jobs, fastest and least likely to be blocked. ON: open each job page (one request per job, paced, slower, more 403-prone; adds full description, expiry, contract length, direct-apply flag) |
Output Fields
One dataset row per job (full field list in the dataset schema; fields the listing does not publish are null, never invented):
- Identity:
id,url,applyUrl(job URL +/apply),title,source,isFeatured,directApply(detail mode only) - Company:
company,companyId,companyUrl,companyLogo,advertiserType(Recruitment Agency / Direct Employer heuristic) - Location:
location,city,region,postcode,country,latitude,longitude(geo centroid) - Compensation:
salaryRaw,salaryMin,salaryMax,salaryCurrency(GBP),salaryPeriod(YEAR/MONTH/WEEK/DAY/HOUR) - Employment:
contractType,contractLength(detail mode),employmentType(detail mode),industry - Dates:
postedText,postedDate,postedDateISO,expiryDate(detail mode),scrapedAt - Description:
descriptionHtml,descriptionText(list mode: from the search payload; detail mode: full page)
Example Input And Output
Example Input
{"searchQuery": "care assistant","location": "Leeds","distance": 15,"contractType": "permanent","maxResults": 200,"includeDescription": false}
Example Output
{"id": "3494812","url": "https://www.cv-library.co.uk/job/3494812/care-assistant-leeds","applyUrl": "https://www.cv-library.co.uk/job/3494812/care-assistant-leeds/apply","title": "Care Assistant - Days","company": "Example Care Homes","companyId": "100234","advertiserType": "Recruitment Agency","location": "Leeds, West Yorkshire","city": "Leeds","region": "West Yorkshire","postcode": "LS1 4AP","country": "GB","latitude": 53.801,"longitude": -1.548,"salaryRaw": "GBP 22,000 - 26,000 per annum","salaryMin": 22000,"salaryMax": 26000,"salaryCurrency": "GBP","salaryPeriod": "YEAR","contractType": "Permanent","industry": "Healthcare","postedText": "2 days ago","postedDate": "2026-10-08","postedDateISO": "2026-10-08T08:00:00Z","isFeatured": false,"descriptionText": "We are looking for a Care Assistant...","source": "cv-library.co.uk","scrapedAt": "2026-10-10T10:00:00.000Z"}
Integrations & Automation
- Apify API - run via
POST https://api.apify.com/v2/acts/{actorId}/runs, export viaGET /v2/datasets/{datasetId}/items?clean=true&format=json - Schedules - Apify Schedules for daily UK job post refreshes (recommended for hiring-trend and market tracking; recurring usage improves Store recommendation signals)
- Webhooks - new-job events into downstream pipelines
- Zapier / Make - via the Apify integration (e.g. new jobs to Google Sheets/Airtable)
- Pay-per-event - $1.00 per 1,000 jobs list mode, $2.40 per 1,000 with full details (
result+detailevents); free 10-job preview
Related Actors
- linkedin-jobs-scraper: the largest job-board scraper on the Store; pairs CV-Library data with LinkedIn reach.
- indeed-scraper: one of the most-used Indeed scrapers for cross-board UK job coverage.
- cv-library-co-uk-scraper: the most-used competing CV-Library actor, for comparison.
- totaljobs-scraper: another major UK job board (Totaljobs) with salary and geo data in the same schema style.
- jobs-workable-scraper: ATS-hosted job postings via clean public JSON APIs.
FAQ
Does CV-Library have an API?
An official partner Job View API (search-jobs-json) exists at cv-library.co.uk/developers but requires a partner API key (returns 400 without it) and is not publicly available. This actor instead reads the site's own search-backend records embedded in the pages as Next.js flight data - the same records the /jobs backend returns, parsed server-side.
How do I scrape CV-Library without getting blocked?
You cannot fully avoid the Cloudflare WAF from a datacenter IP - verified tests show even a genuine Chrome TLS fingerprint still gets 403. This actor solves it for you: at run start a real Chromium warms up the Cloudflare challenge once on a UK residential sticky session, then the CheerioCrawler reuses that same IP + UA. Tested: 0 x 403, 60 jobs in ~7 s. Keep includeDescription OFF for the least 403-prone mode (1 request per 100 jobs).
What are the alternatives for UK job data?
Store alternatives: solidcode/cv-library-co-uk-scraper (most-used, $4.5 per 1K), blackfalcondata/cv-library-scraper ($1.5 per 1K), parseforge ($20.33 per 1K) and unfenced-group ($2 per 1K). This actor is the verified cheapest full-field option at $1.00-2.40 per 1,000. It pairs with own actors totaljobs-scraper and jobs-workable-scraper for multi-board UK coverage.
Why do I get 403 responses occasionally?
The WAF intermittently blocks datacenter IPs even with the warm-up, and includeDescription: true bursts detail-page requests, which is the most likely mode to hit 403s. Fail-safes: a search page backs off 30/60/60 s between attempts then stops with a clear "rate-limited" log; detail pages give up after 2 attempts and fall back to the list-level record; cookie continuity (__cf_bm) is enforced so the clearance survives across requests.
What salary data does CV-Library publish?
salaryRaw (exact text), salaryMin/salaryMax (parsed numbers) and salaryPeriod (YEAR/MONTH/WEEK/DAY/HOUR) in GBP - but only when the employer publishes a salary; otherwise fields are null.
How many jobs can one run return?
Up to 10,000 jobs (maxResults cap). Free Apify users get a 10-job preview per run; paid runs are unlimited up to maxResults. Multiple keywords share the budget across searches.
How much does a run cost?
List mode: $1.00 per 1,000 jobs. With includeDescription: true (full details): $2.40 per 1,000 (result + detail events). Residential warm-up traffic is billed via Apify's residential accounting (~$8 per GB - a list-mode run is only a few MB). Detail mode also costs ~0.7 s pacing per job, so a 1,000-job detail run is ~20 minutes.
SEO Keywords
cv library scraper, cv-library api, uk job scraper, uk jobs api, scrape cv-library, cv library jobs data, uk job listings data, job board scraper, recruitment lead generation, salary benchmarking, uk labour market data, hiring data uk, cv library salary data, job posts monitoring, uk jobs csv, recruitment agencies data, cv library alternative, job hire trends uk, uk job market analysis, candidate sourcing data
For AI Agents & LLM Apps
- Purpose: returns one JSON row per UK job listing from cv-library.co.uk (title, company, advertiser type, location + geo, parsed salary, contract type, dates, description, apply URL).
- Minimal working input:
{ "searchQuery": "software developer", "location": "London", "maxResults": 10, "includeDescription": false }
- Variant input (full details - only when
includeDescription: true):
{ "searchQuery": "care assistant", "maxResults": 50, "includeDescription": true }
- Output field names:
id, url, applyUrl, title, company, companyId, companyUrl, companyLogo, advertiserType, location, city, region, postcode, country, latitude, longitude, salaryRaw, salaryMin, salaryMax, salaryCurrency, salaryPeriod, contractType, contractLength, employmentType, industry, postedText, postedDate, postedDateISO, expiryDate, directApply, isFeatured, descriptionHtml, descriptionText, source, scrapedAt. - Behaviors an agent should know:
includeDescription(default false) is the cost lever: OFF = 1 request per 100 jobs, rows carry list-level description only,nullforcontractLength/expiryDate/directApply/employmentType. ON = one paced request per job and an extradetailpay-per-event charge; rows then carry the full page. Only turn it on when the full description matters.keywordsandsearchQuerycombine: each keyword runs its own search and they all share themaxResultsbudget.startUrlsbypass search construction entirely.daysOldrounds to CV-Library's 1/3/7/14-day bands;distance(0-750 miles) only applies whenlocationis set.salaryMin/salaryMaxare annual GBP filters; salary fields arenullwhen the employer does not publish them - never invent a salary.advertiserTypeis a text heuristic, not an official field.- A 403 in flight is handled internally (fallback to the list-level record); do not re-request failed detail rows - the record is already in the dataset.
maxPages(default 50) is per search, not per run.
- Billing: pay-per-event - $0.001 per job row (list mode), +$0.0014 per job with
includeDescription(detail event), $0.00005 per run start. Residential warm-up traffic billed additionally via Apify residential accounting.
Legal & Compliance Disclaimer
This actor is an independent tool and is not affiliated with, endorsed by, or sponsored by CV-Library Ltd (cv-library.co.uk). It accesses only publicly available job listings and public job pages; it does not bypass login, authentication or paywalls, and it uses a standard browser warm-up only to pass the site's public-facing Cloudflare challenge on a residential IP - it does not circumvent access controls.
Users are responsible for complying with cv-library.co.uk's terms of service, robots.txt and applicable data-protection law (UK GDPR applies to candidate and recruiter data). Use the data for lawful purposes such as market research, salary benchmarking and compliant recruitment workflows, and do not use extracted personal data for unsolicited outreach.