# Totaljobs Scraper \[$0.90/1K💰] | UK Jobs | Salary Data (`ahmed_jasarevic/totaljobs-scraper`) Actor

Scrape UK job listings from totaljobs.com: title, company, location, salary band, contract type, posted/expiry dates, full description, geo and apply URL. Cheerio-based, no browser needed. Pay-per-event.

- **URL**: https://apify.com/ahmed_jasarevic/totaljobs-scraper.md
- **Developed by:** [Ahmed Jasarevic](https://apify.com/ahmed_jasarevic) (community)
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.88 / 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## Totaljobs Scraper - UK Job Listings, Salaries and Full Descriptions

The **Totaljobs Scraper** collects public UK job listings from Totaljobs. Search by keyword and location, or supply exact search and job URLs, and receive job titles, companies, locations, salary bands, normalized salary bounds, contract types, work arrangements, posting and expiry dates, full descriptions, coordinates and apply URLs.

Use it for job market research, salary benchmarking, recruitment lead generation, competitor hiring analysis and job-board aggregation. A fast search pass finds listing cards, and an optional detail pass opens each job page so you can separate fully enriched rows from lightweight search-card rows.

### Main Use Cases for UK Job Listings

- **Job market research** - measure hiring volume by keyword, location, contract type and work arrangement.
- **Salary benchmarking** - compare published salary bands and normalized bounds across roles and regions.
- **Recruitment lead generation** - find companies actively advertising roles and the agencies representing them.
- **Competitor hiring analysis** - track which employers are expanding a team, location or skill set.
- **Job-board aggregation** - feed structured listings into a search product, alert system or internal board.
- **Skills demand analysis** - analyze full descriptions for tools, certifications and seniority signals.
- **Relocation and career research** - compare openings, salaries and work arrangements across UK cities.

### How It Works

![Totaljobs UK job listings becoming structured rows with salaries, companies, locations and full descriptions](https://api.apify.com/v2/key-value-stores/oeuA0kLOyhbRM4fzt/records/how-it-works-totaljobs-scraper.webp)

Set `query` and optional `location` to build a Totaljobs search, or provide search or job detail URLs in `startUrls`. `maxItems` caps saved jobs, `maxPages` limits search pagination, and `maxRequestsPerCrawl` protects the run budget. With `includeDetails` enabled, each selected job page is opened for the full description and enrichment fields.

Search pages are fetched through the site internal result-list JSON endpoint, with an automatic fallback to the server-rendered HTML page. Each page usually contains about 25 jobs. Cards provide the title, company, location, salary text, posting date, expiry date and a description preview before any detail request is made.

Detail pages are parsed from schema.org `JobPosting` JSON-LD and the site preloaded state. This adds the full description text and HTML, contract type, work arrangement, salary bounds, coordinates and the canonical job URL. `detailVerified` is true only when the detail payload was parsed successfully.

If a detail page is blocked or fails, the Actor keeps the search-card row instead of dropping the job. Such rows can have a null description, missing salary bounds and `detailVerified: false`. This design keeps coverage high on a site with aggressive edge protection, but it means you should filter on `detailVerified` when full descriptions are required.

Free users receive at most 10 saved jobs. The site uses Akamai protection, so large runs benefit from a proxy and from conservative `detailConcurrency`. The Actor does not log in and does not submit applications; `applyUrl` points to the canonical Totaljobs job page.

### Input

A keyword and optional location are enough for a standard search. Use start URLs for a fixed query or a known set of job pages.

| Field | Type | Required | Default | What it does |
|---|---|---|---|---|
| `query` | `string` | `No` | `software developer` | Job keyword used to build the search URL. Ignored when startUrls is provided. |
| `location` | `string` | `No` | `Empty` | UK location filter such as London or Manchester. Empty searches the whole UK. |
| `startUrls` | `array` | `No` | `Empty` | Totaljobs search or job detail URLs. Overrides the query and location builder. |
| `maxItems` | `integer` | `No` | `50` | Maximum job records saved in one run. Free users are capped at 10. |
| `maxPages` | `integer` | `No` | `10` | Maximum search-result pages to crawl, roughly 25 jobs per page. |
| `includeDetails` | `boolean` | `No` | `true` | Open job pages for full descriptions, salary bounds, contract type and coordinates. |
| `maxRequestsPerCrawl` | `integer` | `No` | `200` | Hard cap on search and detail HTTP requests. |
| `detailConcurrency` | `integer` | `No` | `6` | Parallel detail workers. Higher values increase the chance of edge blocks. |
| `proxy` | `object` | `No` | `No proxy` | Optional Apify Proxy settings for larger or repeated runs. |

Start with a small `maxItems` and the default detail concurrency to confirm the search and detail paths. Raise `maxPages` for broader coverage, not `detailConcurrency` first. If many rows return `detailVerified: false`, slow the detail workers or enable a proxy before scaling.

### Output

The default dataset contains one row per job. Search-card fields and detail-enriched fields are combined, with a verification flag that tells you which path produced the row.

| Field group | Fields | What you get |
|---|---|---|
| Identity | `jobId`, `title`, `company`, `companyUrl`, `companyLogo`, `url`, `applyUrl`, `source` | Job ID, title, employer, company links, canonical job URL and apply entry point. |
| Location | `location`, `latitude`, `longitude` | Location text and coordinates when the detail page publishes them. |
| Compensation | `salaryBand`, `salaryMin`, `salaryMax`, `salaryCurrency` | Published salary text and normalized bounds in GBP when parseable. |
| Classification | `contractType`, `workArrangement` | Contract type and on-site, remote or hybrid arrangement when published. |
| Dates | `datePosted`, `postedText`, `expiryDate` | ISO posting and expiry timestamps plus relative posting text when available. |
| Description | `descriptionSnippet`, `descriptionText`, `descriptionHtml` | Search-card preview and full detail description in text and HTML. |
| Verification | `detailVerified`, `scrapedAt` | Whether the detail page was parsed and when the row was observed. |

`salaryMin` and `salaryMax` are normalized aids, not a replacement for the published `salaryBand`; a band with a single numeric anchor can produce equal bounds. Rows with `detailVerified: false` may have null description and classification fields. Use `jobId` as the stable key and keep `salaryBand` as the source of truth.

### Pricing

Pricing is pay-per-event. A small start event is charged per run, each saved job is a result event, and each fully enriched job adds a detail event.

| Event | FREE | BRONZE | SILVER | GOLD+ |
|---|---|---|---|---|
| Actor start, per run | $0.00005 | $0.00005 | $0.00005 | $0.00005 |
| Job result | $0.0009 | $0.0009 | $0.00089 | $0.00088 |
| Detail enrichment | $0.0004 | $0.0004 | $0.00039 | $0.00038 |

A saved job costs **$0.90 per 1,000** on FREE and BRONZE, **$0.89 per 1,000** on SILVER and **$0.88 per 1,000** on GOLD and higher. A fully enriched job adds **$0.40 per 1,000** on FREE and BRONZE, **$0.39** on SILVER and **$0.38** on GOLD+. Search-card fallbacks are charged as results but not as detail enrichments. The free preview is capped at 10 jobs.

### Example Input

```json
{
  "query": "software developer",
  "location": "",
  "startUrls": [],
  "maxItems": 3,
  "maxPages": 3,
  "includeDetails": true,
  "maxRequestsPerCrawl": 20,
  "detailConcurrency": 3,
  "proxy": { "useApifyProxy": false }
}
```

This searches UK-wide software developer jobs, keeps three records and enriches each from its detail page. The free preview would stop at 10 rows even with a higher maxItems.

### Example Output

```json
{
  "jobId": "108092727",
  "title": "Software Developer Placement Programme – No experience needed",
  "company": "IT Online Learning",
  "location": "Leeds (LS1)",
  "latitude": 53.7988205,
  "longitude": -1.54985,
  "salaryBand": "From £27,000 to £65,000 per annum",
  "salaryCurrency": "GBP",
  "contractType": "Permanent Contract",
  "workArrangement": "On-site",
  "datePosted": "2026-10-07T11:32:50.497Z",
  "expiryDate": "2026-11-18T12:32:50.497Z",
  "descriptionSnippet": "Software Developer Placement Programme – No experience needed. From £27,000 to £65,000 per annum.",
  "url": "https://www.totaljobs.com/job/software-developer-placement-programme-no-experience-needed/it-online-learning-job108092727",
  "applyUrl": "https://www.totaljobs.com/job/software-developer-placement-programme-no-experience-needed/it-online-learning-job108092727",
  "source": "totaljobs.com",
  "detailVerified": true,
  "scrapedAt": "2026-10-27T17:38:48.297Z"
}
```

This is a real test record with the description shortened. The numeric salary bounds are omitted here; the published `salaryBand` is the authoritative salary text. `detailVerified: true` means the detail page was parsed.

### Integrations and Automation

Run the Actor from the Apify API, Apify MCP, a scheduled task, Zapier, Make, n8n or your own application. Export JSON, CSV, Excel, XML or HTML, or push rows to Google Sheets, Airtable, a recruitment CRM, a data warehouse or a webhook.

Use `jobId` as the stable key and deduplicate across runs. Keep `detailVerified` in your schema and filter on it when full descriptions are mandatory. Preserve `salaryBand` alongside normalized bounds so a downstream salary model can revisit the original text.

For recurring monitoring, schedule a daily or weekly search and compare new job IDs, salary bands and expiry dates. Keep `scrapedAt` with every row so a withdrawn or edited advert has a clear timeline.

### Related Actors

- [CV-Library Scraper](https://apify.com/ahmed_jasarevic/cv-library-co-uk-scraper) - UK job listings with salaries, employers and full descriptions.
- [Reed.co.uk Job Scraper](https://apify.com/ahmed_jasarevic/reed-co-uk-job-scraper) - UK vacancies, salary data and company details.
- [Indeed Job Scraper](https://apify.com/ahmed_jasarevic/indeed-job-scraper) - Job listings, salary signals and company data across markets.

### FAQ

#### Do I need a Totaljobs account?

No. The Actor reads public search and job pages without logging in. It does not submit an application.

#### What does includeDetails do?

It opens each selected job page for the full description, contract type, salary bounds, coordinates and verification flag. Turning it off is faster but leaves many fields empty.

#### Why is detailVerified false?

The detail page was blocked, timed out or unparseable, so the Actor kept the search-card row. Retry with lower detail concurrency or a proxy.

#### Are salaryMin and salaryMax exact?

They are normalized from the published salary text when possible. Use `salaryBand` as the source of truth, especially when the advert gives a range or a single anchor.

#### Is there a free preview cap?

Yes. Free users can save at most 10 jobs per run. Detail enrichment is charged only for rows that were actually enriched.

#### Can I scrape a specific search URL?

Yes. Put the search URL in `startUrls`. Any filters encoded in that URL are preserved in the API request.

### For AI Agents and LLM Apps

The Actor returns compact UK job records with salary, classification, dates and a detail-verification flag, suitable for market analysis and recruitment enrichment.

- One row represents one public Totaljobs advert. Use `jobId` as the key and `scrapedAt` as the observation time.
- `detailVerified` distinguishes fully enriched rows from search-card fallbacks. Do not assume every row has a full description.
- `salaryBand` is the published salary text; `salaryMin` and `salaryMax` are normalized aids and can be incomplete or equal.
- `descriptionText` and `descriptionHtml` can be null when details were not fetched or the page was blocked. Missing data is not a zero value.
- The free preview is limited to 10 jobs; result and detail-enrichment events are billed separately.

### Legal and Compliance

This Actor is an independent tool and is not affiliated with, endorsed by or sponsored by Totaljobs. It reads publicly visible job adverts for legitimate market research and recruitment analysis. The source platform terms and applicable law still apply.

Job adverts can contain personal data and company-confidential text. Use the data for a lawful purpose, keep a documented basis where required, honor deletion and opt-out requests, and do not republish full descriptions in a way that infringes copyright or misrepresents the employer.

### SEO Keywords

Totaljobs scraper, UK job listings, Totaljobs API alternative, UK salary data, job board scraper, software developer jobs UK, Totaljobs dataset, UK recruitment data, job market research, salary benchmarking UK, Totaljobs JSON export, UK vacancies, job posting scraper, hiring data UK, Totaljobs search scraper, UK jobs dataset, salary bands UK, recruitment leads, job description data, UK employment market

# Actor input Schema

## `query` (type: `string`):

Job keyword, e.g. "software developer", "nurse", "plumber". Used to build the Totaljobs search URL (ignored when Start URLs are provided).

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

UK location filter, e.g. "London", "Manchester". Leave empty to search the whole UK.

## `startUrls` (type: `array`):

Direct Totaljobs search (/jobs/...) or job detail (/job/...) URLs to scrape. When provided, Search keyword / Location are ignored.

## `maxItems` (type: `integer`):

Maximum number of job records to return. Free users are capped at 10 items per run.

## `maxPages` (type: `integer`):

Maximum number of search-result pages to crawl (â‰ˆ25 jobs per page). Kept high by default so Max items is never silently capped â€” the crawl still stops as soon as the item budget is filled.

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

Open each job detail page for the full description, salary band, contract type, posted/expiry dates and geo coordinates. Slower and each enriched job adds a small pay-per-event surcharge. Turn off for fast title/company/location-only runs.

## `maxRequestsPerCrawl` (type: `integer`):

Safety cap on total HTTP requests (search pages + detail pages).

## `detailConcurrency` (type: `integer`):

How many job detail pages to fetch in parallel (1â€“10). The site's Akamai edge reliably sustains about 5â€“6 concurrent detail fetches from datacenter IPs; higher is faster when the edge is calm, but bursts above that get refused and rows fall back to search-card data (detailVerified: false).

## `proxy` (type: `object`):

Select proxies to be used by your crawler.

## Actor input object example

```json
{
  "query": "software developer",
  "location": "",
  "startUrls": [],
  "maxItems": 50,
  "maxPages": 10,
  "includeDetails": true,
  "maxRequestsPerCrawl": 200,
  "detailConcurrency": 6,
  "proxy": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

No description

# 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 = {
    "query": "software developer",
    "location": "",
    "startUrls": [],
    "proxy": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("ahmed_jasarevic/totaljobs-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 = {
    "query": "software developer",
    "location": "",
    "startUrls": [],
    "proxy": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("ahmed_jasarevic/totaljobs-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 '{
  "query": "software developer",
  "location": "",
  "startUrls": [],
  "proxy": {
    "useApifyProxy": false
  }
}' |
apify call ahmed_jasarevic/totaljobs-scraper --silent --output-dataset

```

## MCP server setup

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