# Totaljobs & CWJobs Scraper — UK Jobs & Salaries, No Phones (`highbrow_fame/totaljobs-jobs`) Actor

UK jobs from Totaljobs and CWJobs: title, company, location, salary as text and as min/max/period, contract type, posted date and the full job ad. No recruiter names or phones.

- **URL**: https://apify.com/highbrow\_fame/totaljobs-jobs.md
- **Developed by:** [yestrue](https://apify.com/highbrow_fame) (community)
- **Categories:** Jobs
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.20 / 1,000 job delivereds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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 & CWJobs Scraper — UK Jobs & Salaries, No Phones

Get UK job listings from Totaljobs and its sister site for IT and tech jobs, CWJobs: job title, company, location and postcode, the salary as the employer wrote it plus the parsed minimum, maximum, currency and period (per year, day or hour), posted date and a short snippet — and, if you want, the full ad as plain text, the contract type, whether the work is on-site, hybrid or remote, industry and the date the ad runs until. Paste your Totaljobs or CWJobs search links — or just type a keyword and a place.

**Why this one**

- 🔗 **Your search, as you set it up.** Set every filter you like on totaljobs.com or cwjobs.co.uk and paste the link. Or type keywords here — nurse, HGV driver, python developer — with a place and a radius, and choose the site, posted within, job type (permanent, contract, temporary, part time, work from home), direct employers or agencies, and newest first below.
- ⚡ **Fast.** A live test run read three searches — CWJobs software developers, Totaljobs nurses within 20 miles of Manchester, HGV drivers around Leeds — 1,301 jobs in 70 seconds.
- 💷 **Salaries, parsed.** 1,253 of those 1,301 jobs showed a salary. "£30000 - £40000 per annum", "Up to £525 per day", "From £14 to £15 per hour" become `salaryMin`, `salaryMax`, `salaryCurrency` and `salaryPeriod` (746 jobs); the rest said things like "Competitive" (233), "Unspecified" (186) or "Negotiable" (37).
- 📅 **"Posted within" means posted within.** The sites' own filter lets older ads through: a live "care assistant in Bristol, last 3 days" search listed 40 jobs, 32 of them older. The run checks the posting date and leaves those out.
- 📄 **Full ads when you need them.** Tick **Open every job ad** for the ad text, contract type and on-site / hybrid / remote. A live run read 88 jobs with their ads in 22 seconds.
- 🔒 **No recruiter names, no phone numbers.** Contact persons are not output, and phone numbers, e-mail addresses and recruiters' names written into the ads are replaced with `[phone removed]`, `[e-mail removed]` and `[name removed]` (in a live run of 46 ads: 5 phone numbers and 5 names).
- 💸 **You pay only for jobs delivered.** A link that is not a Totaljobs or CWJobs search, or a place the site does not know, comes back as a free record with the reason.

### What you get

For every job:

| Field | What it is |
|---|---|
| `jobId`, `url`, `title`, `site` | the job ad, and whether the search was on Totaljobs or CWJobs |
| `company`, `companyId`, `companyUrl`, `companyLogo` | the employer or recruitment agency (none when the ad is anonymous) |
| `location`, `postcode` | where the job is, and its postcode (district or full) when given |
| `salary`, `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod` | the salary as written, and parsed (`year`, `month`, `week`, `day` or `hour`) |
| `postedAt`, `featured` | when it was posted; a featured ad |
| `match`, `snippet` | `keyword` or `related` (a few related jobs the site adds), and the start of the ad text |
| `input`, `position`, `scrapedAt`, `status`, `error` | which search it came from, and why a search gave nothing |

With **Open every job ad** also: `description` (the full ad as plain text), `contractType` ("Permanent Contract; Hybrid"), `workplace` (`on-site`, `hybrid` or `remote`), `workType`, `employmentType`, `industry`, `city`, `region`, `countryCode`, `validThrough`.

#### Example

A real record from a live run with the ads opened — accountant jobs around Leeds, 25 September 2026 (the snippet and the description are cut here):

```json
{
  "site": "Totaljobs",
  "jobId": 107936382,
  "url": "https://www.totaljobs.com/job/management-accountant/marks-sattin-uk-ltd-job107936382",
  "title": "Management Accountant",
  "company": "Marks Sattin (UK) Ltd",
  "companyId": 1378246,
  "location": "Bradford (BD1), BD1",
  "postcode": "BD1",
  "salary": "£48000 - £53000 per annum + Hybrid, flexi time, healthcare",
  "salaryMin": 48000,
  "salaryMax": 53000,
  "salaryCurrency": "GBP",
  "salaryPeriod": "year",
  "postedAt": "2026-09-03T17:25:26.29Z",
  "featured": false,
  "match": "keyword",
  "snippet": "Qualified Management Accountant role working for one of the major businesses that this company owns with genuine progression opportunities and excellent wider benefits package. …",
  "contractType": "Permanent Contract; Hybrid",
  "workplace": "hybrid",
  "employmentType": "FULL_TIME",
  "industry": "Accountancy, Accountancy-Accountancy",
  "city": "Bradford",
  "region": "Yorkshire",
  "countryCode": "GB",
  "validThrough": "2026-10-15T17:25:26.29Z",
  "description": "Qualified Management Accountant role working for one of the major businesses that this company owns with genuine progression opportunities and excellent wider benefits package.\nClient Details\n…",
  "status": "OK"
}
```

### How to use it

1. Paste **Search links** from totaljobs.com or cwjobs.co.uk, one per line — or type **Keywords** and a **Place**, pick the **Site** and choose the filters.
2. Set **Max jobs per search**, and tick **Open every job ad** if you need the full ads.
3. Press **Start**, and download the results from the **Output** tab as JSON, CSV or Excel.

To follow new jobs, save your input as a task with **Posted within (days)** set to 1 and schedule it daily.

You can also call it from the Apify API, from Make, Zapier or n8n, or from an AI agent through the Apify MCP server.

**Proxy.** Totaljobs and CWJobs turn away requests from data centres: from Apify's servers a direct request got no answer in 30 seconds and Apify's datacenter proxy got HTTP 403. So the run goes through **Apify's UK residential proxies by default** (Proxy: Residential, United Kingdom). Leave it as it is, or put your own UK proxy there.

### Pricing

You are charged **per job delivered** — see the price on this page. Opening the job ads costs nothing extra, only time. Links that are not Totaljobs or CWJobs searches, and places the site does not know, are free.

### FAQ

**How many jobs per search?** As many as the site lists: the run reads page after page. In the live run the CWJobs software developer search stopped at the 1,000 jobs set as the maximum, of 3,114. Set **Max jobs per search** as high as you need.

**Why are some jobs outside the place I typed?** The site searches a radius around the place (set it with **Radius**, 0 to 30 miles), so in a live run an accountant search in Leeds also brought jobs in Bradford. The `location` and `postcode` fields say where each job is.

**Why does a CWJobs job link go to totaljobs.com?** The two sites share their jobs; CWJobs itself links its jobs to totaljobs.com (all 1,000 in the live run), and the link opens the same ad.

**Why no recruiter names or phone numbers?** They are personal data. Every job has its `url`; you apply on the site.

**Is this affiliated with Totaljobs or CWJobs?** No. This is an independent tool that reads public Totaljobs and CWJobs job listings.

**Like it?** A short review on the Store page helps other people find this Actor. Something missing or broken? Tell us on the Issues tab — we read every one.

# Actor input Schema

## `searchUrls` (type: `array`):

Set up a search on totaljobs.com or cwjobs.co.uk with all the filters you want and paste the address of the results page. One per line.

## `keywords` (type: `array`):

Or search here without a link: job titles or keywords (nurse, python developer, HGV driver). One search per line; the place and filters below apply to each.

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

A town, city, postcode or county (Leeds, M1, Kent). Empty: the whole UK. With a place and no keywords, you get every job there.

## `site` (type: `string`):

Which site the keywords search. CWJobs is Totaljobs' sister site for IT and tech jobs. A link decides this itself.

## `radiusMiles` (type: `integer`):

Optional: jobs this far around the place — 0, 5, 10, 20 or 30 miles; other numbers round up. The site's default is 10.

## `postedWithinDays` (type: `integer`):

Optional: only jobs from the last 1, 3, 7 or 14 days; other numbers round up. 0: any date.

## `jobType` (type: `string`):

Optional.

## `companyType` (type: `string`):

Optional: only jobs posted by the employer itself, or only by recruitment agencies.

## `sortBy` (type: `string`):

For the keywords above.

## `includeRelatedJobs` (type: `boolean`):

The site adds a few related jobs after the ones that match the keyword and counts them in its result number. Untick to keep only the jobs that match the keyword; the field match says which is which.

## `maxJobsPerSearch` (type: `integer`):

Stops each search after this many jobs.

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

Adds the full job ad as plain text, the contract type (permanent, contract, temporary), whether the work is on-site, hybrid or remote, full or part time, industry and the date the ad runs until. One more page per job, so slower.

## `maxConcurrency` (type: `integer`):

How many searches to work on at the same time.

## `proxyConfiguration` (type: `object`):

Totaljobs and CWJobs turn away requests from data centres (Apify's own servers and its datacenter proxy both got HTTP 403 or no answer), so the run goes through UK residential proxies.

## Actor input object example

```json
{
  "searchUrls": [
    "https://www.totaljobs.com/jobs/accountant/in-manchester?radius=10"
  ],
  "site": "totaljobs",
  "postedWithinDays": 0,
  "jobType": "any",
  "companyType": "any",
  "sortBy": "relevance",
  "includeRelatedJobs": true,
  "maxJobsPerSearch": 30,
  "includeDetails": false,
  "maxConcurrency": 3,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "GB"
  }
}
```

# Actor output Schema

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

Every result as a JSON record, with a status for each input.

## `resultsCsv` (type: `string`):

The same records as CSV, for a spreadsheet.

# 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 = {
    "searchUrls": [
        "https://www.totaljobs.com/jobs/accountant/in-manchester?radius=10"
    ],
    "maxJobsPerSearch": 30,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "GB"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("highbrow_fame/totaljobs-jobs").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 = {
    "searchUrls": ["https://www.totaljobs.com/jobs/accountant/in-manchester?radius=10"],
    "maxJobsPerSearch": 30,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "GB",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("highbrow_fame/totaljobs-jobs").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 '{
  "searchUrls": [
    "https://www.totaljobs.com/jobs/accountant/in-manchester?radius=10"
  ],
  "maxJobsPerSearch": 30,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "GB"
  }
}' |
apify call highbrow_fame/totaljobs-jobs --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,highbrow_fame/totaljobs-jobs"
        }
    }
}
```

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/2jpz1bkx3rMubZacT/builds/pJsuLT0GsNZrDdohP/openapi.json
