Totaljobs Scraper - UK Job Board avatar

Totaljobs Scraper - UK Job Board

Pricing

from $0.79 / 1,000 jobs

Go to Apify Store
Totaljobs Scraper - UK Job Board

Totaljobs Scraper - UK Job Board

Scrape job listings from Totaljobs.com by keyword and location. Get titles, employers, salaries, full descriptions, company details, and incremental change tracking. Export as JSON, CSV, or Excel.

Pricing

from $0.79 / 1,000 jobs

Rating

0.0

(0)

Developer

ParseBird

ParseBird

Maintained by Community

Actor stats

1

Bookmarked

3

Total users

2

Monthly active users

a day ago

Last modified

Categories

Share

Totaljobs Scraper

Scrape job listings from Totaljobs.com, one of the UK's largest job boards, into clean, structured JSON. The Totaljobs Scraper searches by keyword and location, pulls the job title, employer, salary, full description, postcode, and geo-coordinates, and can track what changed between scheduled runs — without the Totaljobs API.

Search any keyword across any UK town or region, apply 15+ filters (contract type, salary, posting date, radius in miles, remote, keyword rules, custom field rules), enrich each job with its full description, employment type and industry, and turn on incremental mode to get only NEW / UPDATED / EXPIRED jobs.

Copy to your AI assistant

Copy this block into ChatGPT, Claude, Cursor, or any LLM to start using this actor.

Actor: parsebird/totaljobs-scraper (Apify). Scrapes job listings from totaljobs.com (UK) by keyword and location. Call with ApifyClient.
Input JSON fields: query: string or JSON array of strings — job keywords; location: string or JSON array — UK city/region; startUrls: string[] — Totaljobs search or job URLs (overrides query/location); sort: "relevance"|"date"|"salary_low"|"salary_high"; age: int — keep jobs posted within the last N days; remote: bool; radius: "5"|"10"|"20"|"30" miles (others reduced to 30); minSalary: int GBP/year; contractType: FULL_TIME|PART_TIME|CONTRACT|TEMPORARY|INTERNSHIP|APPRENTICESHIP|FREELANCE|MINI_JOB|WORKING_STUDENT|VOLUNTEER|THESIS|DUAL_STUDY; workType: FULL_TIME|PART_TIME; experience: no|required|executive; companyId: int; language: e.g. "en"; applicationMethod: INTERNAL|EXTERNAL; excludeSponsored: bool; includeKeywords/excludeKeywords: {"keywords":[...],"matchTitle":true,"matchDescription":true,"matchSkills":true}; fromDate/toDate: YYYY-MM-DD; maxAgeMinutes: int; customFilters: [{"field":"unifiedSalary.min","op":"gte","value":50000}]; includeDetails: bool (default true); descriptionFormat: html|text|markdown|original; maxResults: int (default 100, 0=unlimited); maxPages: int (default 10); compact: bool; descriptionMaxLength: int; excludeEmptyFields: bool; outputFields: string[] (dot notation ok); datasetName: string; mode: "full"|"incremental"; stateStoreName: string (default totaljobs-state); emitUnchanged/emitExpired/skipReposts: bool; dedupStoreName: string; dedupKey: string (default jobKey); proxyConfiguration: object (UK RESIDENTIAL preset).
Output: one item per job — jobKey, legacyJobId, harmonisedId, title, company, companyId, companyUrl, companyLogoUrl, companyWebsite, companyRating, location, postCode, locationDetail{city,region,country,postalCode,lat,lng}, description, descriptionLength, textSnippet, textSnippetCleaned, unifiedSalary{min,max,currency,period,salaryAvailable}, salaryText, workFromHome, employmentType, contractType, directApply, applicationMethod, industry, language, isSponsored, isTopJob, isHighlighted, isAnonymous, hasFuturePosting, partnership{isPartnershipJob,isCrossPosted,isBackfilled}, metaData{positionOnPage,positionAbsolute}, section, topLabels, skills, datePosted, postedDaysAgo, publishFromDate, publishToDate, validThrough, canonicalUrl, url, portalUrl, geo, query, scrapedAt, detailsFetched, similarJobCount, isRepost. Incremental mode adds changeType, firstSeenAt, lastSeenAt, repostOfId, repostDetectedAt.
Example: { "query": "data engineer", "location": "London", "maxResults": 50 }
API: https://api.apify.com/v2/acts/parsebird~totaljobs-scraper · Token: https://console.apify.com/account/integrations

What does Totaljobs Scraper do?

Totaljobs.com lists hundreds of thousands of live vacancies across the United Kingdom. There is no public Totaljobs search API — this scraper reads the site's own search results and job pages and returns them as structured data. For every keyword and location it extracts:

  • 🏷️ Job identity — title, employer, location, postcode, remote flag, and a canonical totaljobs.com/job/... link.
  • 💰 Pay — the salary text as shown, plus a normalised unifiedSalary object with min, max, currency, and pay period (year / month / week / day / hour).
  • 📋 Full description (optional) — the complete job description as HTML, plain text, Markdown, or the site's original format.
  • 🏢 Employer data — company name, numeric ID, logo, and — where the employer has a Totaljobs profile — website and rating.
  • 📅 Dates — when the job was posted, how many days ago, and when the listing expires (validThrough).
  • 📊 Placement signals — sponsored / top-job / highlighted flags and the position the job held on the results page.
  • 🌍 Geo — city, region, country, postcode, latitude and longitude from the job page.

Turn on incremental mode and each run compares against the last one with the same state store, so you get only the jobs that are NEW, UPDATED, REAPPEARED, or EXPIRED.

What data can you extract from Totaljobs?

FieldDescription
jobKeyTotaljobs' own numeric listing ID (stable identity)
legacyJobId / harmonisedIdNumeric and UUID identifiers
titleJob title
company / companyIdEmployer name and numeric ID
companyUrl / companyLogoUrl / companyWebsite / companyRatingEmployer links and profile data
location / postCode / locationDetailDisplay location, postcode, plus city / region / country / lat / lng
unifiedSalarymin, max, currency, period, salaryAvailable
salaryTextSalary exactly as shown on the listing
description / descriptionLengthFull description in your chosen format (with includeDetails)
employmentType / contractType / workArrangementSchema.org type, permanence label, and on-site / hybrid / remote
workFromHome / directApply / applicationMethodRemote flag and how to apply
industry / skillsIndustry classification and tagged skills
datePosted / postedDaysAgo / validThroughPosting and expiry timing
isSponsored / isTopJob / isHighlighted / hasFuturePostingPlacement and status signals
similarJobCountNumber of similar jobs Totaljobs shows on the page
url / canonicalUrl / sourceUrlJob link, canonical link, and the search page it came from
changeType / firstSeenAt / lastSeenAtAdded in incremental mode

Not every listing has every field — salary, employer profile, and exact skills vary by posting.

Input parameters

ParameterTypeRequiredDefaultDescription
querystring / arrayNo*Job keyword(s). JSON array runs multiple searches.
locationstring / arrayNo*UK city or region. JSON array for multiple.
startUrlsarrayNo*Totaljobs search or job URLs (overrides query/location).
sortstringNorelevancerelevance, date, salary_low, salary_high.
ageintegerNoKeep only jobs posted within the last N days.
remotebooleanNofalseRemote / work-from-home only.
radiusstringNoSearch radius in miles (5 / 10 / 20 / 30 answered).
minSalaryintegerNo0Minimum annual salary (GBP).
contractType / workType / experiencestringNoEmployment-type filters (applied to each job).
companyIdintegerNoRestrict to one employer by numeric ID.
language / applicationMethodstringNoPosting language / apply method filters.
excludeSponsoredbooleanNofalseDrop promoted listings.
includeKeywords / excludeKeywordsobjectNoKeyword rules on title / description / skills.
fromDate / toDate / maxAgeMinutesstring / integerNoDate-window filters.
customFiltersarrayNoField-level rules (gte, includes, …).
includeDetailsbooleanNotrueFetch each job's detail page.
descriptionFormatstringNohtmlhtml / text / markdown / original.
maxResultsintegerNo100Max jobs to return (billed rows). 0 = unlimited.
maxPagesintegerNo10Max result pages (25 jobs/page). Auto-raised as needed.
compact / descriptionMaxLength / excludeEmptyFields / outputFieldsNoOutput-shaping options.
datasetNamestringNoPush to a custom named dataset ({DATE} / {TIME} masks).
modestringNofullfull or incremental change tracking.
stateStoreName / emitUnchanged / emitExpired / skipRepostsNototaljobs-stateIncremental-mode settings.
dedupStoreName / dedupKeystringNoCross-run deduplication (full mode).
proxyConfigurationobjectNoUK RESIDENTIALApify Proxy settings.

* Provide at least one of query, location, or startUrls.

Example input

{
"query": "data engineer",
"location": "London",
"contractType": "FULL_TIME",
"minSalary": 60000,
"maxResults": 100
}

Incremental tracking:

{
"query": "data engineer",
"maxResults": 200,
"mode": "incremental",
"stateStoreName": "data-engineer-tracker"
}

Output example

{
"jobKey": "106464063",
"legacyJobId": 106464063,
"harmonisedId": "ac402b3b-a5cb-472a-b535-d3abba5c5b2f",
"title": "Domestic Appliance Engineer",
"company": "RECRUIT123 LIMITED",
"companyId": 1051840,
"companyUrl": "https://www.totaljobs.com/jobs/recruit123?cmpId=1051840&cmp=1",
"companyLogoUrl": "https://www.totaljobs.com/CompanyLogos/4360d0fffa3c441b93f31e568ccfefb8.png",
"location": "Birmingham (B33), B33",
"postCode": "B33",
"locationDetail": { "city": "Birmingham", "region": "West Midlands", "country": "GB", "postalCode": "B33", "lat": 52.48075, "lng": -1.79307 },
"unifiedSalary": { "min": null, "max": null, "currency": null, "period": null, "salaryAvailable": false },
"salaryText": "Competitive salary",
"description": "<p><b>Are you looking for a role that offers flexibility?</b></p>...",
"descriptionLength": 2025,
"workFromHome": false,
"employmentType": "FULL_TIME",
"contractType": "Permanent",
"directApply": true,
"applicationMethod": "INTERNAL",
"industry": "Engineering, Engineering-Maintenance",
"language": "en",
"isSponsored": false,
"topLabels": ["NEW"],
"datePosted": "2026-01-06T08:06:14.8Z",
"postedDaysAgo": 2,
"validThrough": "2026-02-17T08:06:14.8Z",
"canonicalUrl": "https://www.totaljobs.com/job/domestic-appliance-engineer/recruit123-limited-job106464063",
"url": "https://www.totaljobs.com/job/domestic-appliance-engineer/recruit123-limited-job106464063",
"portalUrl": "https://www.totaljobs.com",
"geo": "TOTALJOBS",
"query": "engineer",
"scrapedAt": "2026-09-09T10:00:00.000Z",
"detailsFetched": true,
"similarJobCount": 10,
"isRepost": false
}

Download the dataset as JSON, CSV, Excel, XML, or HTML from the Storage tab or the Apify API.

How to scrape Totaljobs

  1. Open the Input tab of the Totaljobs Scraper.
  2. Enter a search term — a job title or skill such as data engineer or care assistant.
  3. Optionally set a location (London, Manchester), a contract type, a minimum salary, a radius in miles, and a "posted within" window.
  4. Set Max results — start with 25–50 to keep the first run fast and cheap.
  5. Click Start. Results stream into the dataset as they are scraped.
  6. Export from the Storage tab, pull the data via API, or connect an integration (Google Sheets, Slack, Zapier, Make, webhooks).

To scrape Totaljobs on a schedule, use Apify Schedules and set mode to incremental so each run returns only what changed.

Python and JavaScript API examples

from apify_client import ApifyClient
client = ApifyClient("<YOUR_API_TOKEN>")
run = client.actor("parsebird/totaljobs-scraper").call(run_input={
"query": "data engineer",
"location": "London",
"maxResults": 50,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item["title"], item["company"], item["unifiedSalary"])
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_API_TOKEN>' });
const run = await client.actor('parsebird/totaljobs-scraper').call({
query: 'data engineer',
location: 'London',
maxResults: 50,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);

Filtering and monitoring

  • Server-side filters (handled by Totaljobs' own search): keyword, location, contract prefix, minimum salary, radius in miles.
  • Client-side filters (applied to each parsed job): posted-within days, work type, experience, company ID, language, application method, sponsored, include/exclude keywords, date window, max age, and free-form customFilters on any output field (dot notation, e.g. unifiedSalary.min).
  • Incremental mode: set mode to incremental and reuse a stateStoreName. The first run records a baseline; later runs emit only NEW / UPDATED / REAPPEARED jobs (add emitUnchanged / emitExpired for the rest). Reposts of expired jobs are detected and tagged.
  • Cross-run dedup: in full mode, set dedupStoreName to push only jobs never seen in previous runs with that store.

How much does it cost to scrape Totaljobs?

This actor uses pay-per-result pricing:

PlanPrice per 1,000 jobs
Free$0.99
Bronze$0.89
Silver$0.89
Gold$0.79

One event is charged per job row pushed to the dataset. Scraping 100 jobs with full details costs about $0.10 on the Free plan. Apify platform usage (compute + UK residential proxy) is billed separately per your plan.

Use cases

  • 📈 UK job-market research — track vacancy volume and salaries for a role or sector over time.
  • 🧭 Recruiting and sourcing — monitor new listings in a city and category every morning.
  • 💷 Salary benchmarking — aggregate unifiedSalary.min / unifiedSalary.max by role, seniority, and location.
  • 🔁 Job-board aggregation — feed Totaljobs listings into your own product alongside other sources.
  • 🔔 Alerting — schedule with mode: incremental + maxAgeMinutes: 60 and route new jobs to Slack or a webhook.

How it works

  1. The actor builds a Totaljobs search URL from your keyword, location, minimum salary and radius, and requests it through Apify's UK residential proxy.
  2. It reads the listing data embedded in each results page and follows pagination up to maxPages (25 jobs per page), deduplicating by job key.
  3. With includeDetails on (or when a client-side filter needs it), it opens each job page for the full description, employment type, industry, ISO dates, and geo-coordinates.
  4. Client-side filters run, incremental diffing or cross-run dedup is applied, output is shaped, and each row is pushed and billed once.

FAQ

Do I need a Totaljobs account? No. The scraper only reads public search results and job pages.

Why do some jobs have no salary or employer profile? Many UK listings show "Competitive" instead of a figure, and employer profiles (website, rating) exist only for companies with a Totaljobs company page. Every other field is still returned.

Why is the radius in miles? Totaljobs is a UK board and its search works in miles. Only 5, 10, 20 and 30 are answered by the site; any other choice is reduced to 30 miles (about 48 km) and noted in the run log.

How do the advanced contract types map? Totaljobs' search supports a few contract prefixes (permanent, part-time, contract, temporary, work-from-home). Values like INTERNSHIP or FREELANCE are mapped to the closest prefix and then enforced against each job's parsed employment type.

Can I run this on a schedule? Yes. Use Apify Schedules with mode: incremental, and webhooks or integrations to route new jobs into your tools.

Something looks wrong or a field is missing. Open an issue on the Issues tab with your input and the run ID.

Scraping publicly available data is legal in most jurisdictions, and this actor only reads pages any visitor can load without logging in. It does not bypass authentication and does not collect personal data about individuals. You are responsible for how you use the data — review Totaljobs' Terms and Conditions and Apify's guide on the legality of web scraping before large-scale or commercial use.

Browse all ParseBird actors for more job boards and data sources.