# CWJobs Job Data: Live UK Tech Jobs API (`b2b_leads/cwjobs-real-time-data-scraper`) Actor

Collect live UK tech jobs from CWJobs in real time. Keyword + location search, company tracking, full description enrichment, and URL lookup — streamed to your dataset with webhook delivery.

- **URL**: https://apify.com/b2b_leads/cwjobs-real-time-data-scraper.md
- **Developed by:** [Emmanuel](https://apify.com/b2b_leads) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $9.00 / 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.

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

## CWJobs Real-Time Data

Live UK tech job listings from CWJobs, structured and streaming. Search by keyword and location, follow companies, enrich full descriptions, or refresh saved URLs — every record lands in your dataset the moment it is finalized, with optional real-time webhook delivery.

> **Free-trial notice:** on the Apify free plan each run returns a 2-result sample. Upgrade to a paid Apify plan for full, unlimited data.

### Who it is for

Recruiters and sourcers building live UK tech pipelines, startup researchers tracking who is hiring, job-board aggregators, salary-benchmarking analysts, and agencies feeding CRMs with fresh openings.

**Use cases**

- Track live openings per role and city (e.g. DevOps in Manchester, Data roles in London)
- Watch target employers and get alerted to new postings
- Benchmark advertised salaries across regions and seniorities
- Feed Sheets/CRM/Slack with new matches via webhook as they stream
- Refresh a saved shortlist of postings on a schedule
- Power AI agents that answer “who is hiring for X in Y right now?”

### Features

| Checkbox | What you get |
|---|---|
| 💼 Job search (default on) | Keyword + UK location search. Fast cards: title, company, logo, location, salary, snippet, posting age |
| ✨ Fetch full details | Enriches the same row with the full description and extra fields. Nothing is ever dropped |
| 🏢 Company jobs | One live search per company name — openings at the employers you name |
| 🔗 Scrape by URL | Paste CWJobs job URLs to collect them as rows |
| 📣 Webhook delivery | Every row is saved to the dataset and optionally pushed to your URL (JSON or Slack) in real time |

### Input reference

| Field | Type | Default | Example |
|---|---|---|---|
| `enableJobSearch` | checkbox | `true` | — |
| `jobKeywords` | string list | `["software engineer"]` | `["devops engineer", "data analyst"]` |
| `jobLocation` | text | `"London"` | `"Manchester"`, `"Remote"`, `"United Kingdom"` (nationwide) |
| `jobsPerQuery` | number (1–1000) | `10` | `25` |
| `fetchFullDetails` | checkbox | `false` | `true` adds full descriptions to the same rows |
| `enableCompanyJobs` | checkbox | `false` | `true` + names below |
| `companyNames` | string list | `[]` | `["Barclays", "BBC"]` |
| `jobsPerCompany` | number (1–1000) | `10` | `20` |
| `enableScrapeByUrl` | checkbox | `false` | `true` + URLs below |
| `jobUrls` | string list | `[]` | `["https://www.cwjobs.co.uk/job/..."]` |
| `webhookUrl` | text | `""` | `https://hooks.slack.com/...` |
| `webhookFormat` | `json` | `slack` | `"json"` | `"slack"` for Slack-friendly messages |
| `proxyConfiguration` | proxy | Residential, `GB` | Residential GB recommended for the freshest UK results |

Leave everything else off for the fastest demo: one keyword, London, 10 jobs — results in seconds.

### Output fields

Each dataset row: `featureType`, `jobId`, `title`, `company`, `companyLogo`, `location`, `salary` (+ `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod`), `snippet`, `postedAt`, `postedText`, `employmentType`, `descriptionText` (with full-details on), `detailsFetched`, `jobUrl`, `searchQuery`, `searchLocation`, `position`, `source`, `scrapedAt`.

The `OUTPUT` value summarizes the run: `totalPushed`, `enabledFeatures`, `errors`, `spendingLimitReached`, and a `paywall` transparency object.

### Webhooks (JSON + Slack)

Set `webhookUrl` to also push every record in real time — your CRM automation URL, a Slack incoming webhook, Zapier, Make, or Sheets. Choose `webhookFormat` `json` (full record) or `slack` (readable message). Delivery is fire-and-forget: a failing webhook never stops the run, and the dataset always has every row.

### MCP / AI-agent usage

Pair with the Apify MCP server: point your agent at this Actor and ask, for example:

> “Find live DevOps Engineer jobs in Manchester on CWJobs and send me the top 5 with salaries.”

The agent starts a run with `jobKeywords: ["DevOps Engineer"]`, `jobLocation: "Manchester"`, reads the dataset rows, and summarizes.

### FAQ

- **Which proxy should I use?** Residential proxies default to GB on the platform — they give the freshest UK results. Local runs use the same routing via env config.
- **How much of the free plan can I use?** Free-plan runs return a 2-result sample per run; paid plans are uncapped.
- **How fresh is the data?** Every run collects live listings at run time — what you see on CWJobs now is what lands in your dataset.
- **Does full-details slow things down?** It adds a little extra time per record to enrich full descriptions; the same rows are exported either way.
- **Why is a row missing its description?** The fast card is always exported; if the full view was momentarily unavailable the row still lands with `detailsFetched: false`.

# Actor input Schema

## `enableJobSearch` (type: `boolean`):

Search live CWJobs listings by keyword and UK location. Returns fast cards: title, company, location, salary when shown, snippet, and posting age. On by default.

## `jobKeywords` (type: `array`):

Keywords for the CWJobs search, e.g. "software engineer", "data analyst", "devops engineer". One search runs per keyword.

## `jobLocation` (type: `string`):

UK location to search in, e.g. "London", "Manchester", "Remote". Leave empty or use "United Kingdom" to search nationwide.

## `jobsPerQuery` (type: `integer`):

Cap the number of jobs collected per keyword search. This is the main cost lever for job search.

## `fetchFullDetails` (type: `boolean`):

Enrich each job row in place with its full description and extra fields when available. Every job is still exported even when details are unavailable (nothing is dropped). Adds a little extra time per record.

## `enableCompanyJobs` (type: `boolean`):

Collect live openings at specific companies by name, e.g. "Barclays", "BBC". Runs one CWJobs search per company. Off by default — turn on and add company names.

## `companyNames` (type: `array`):

Company names to collect openings for (only used when Company jobs is enabled).

## `jobsPerCompany` (type: `integer`):

Cap the number of jobs collected per company.

## `enableScrapeByUrl` (type: `boolean`):

Collect job records from explicit CWJobs job URLs (cwjobs.co.uk/job/...). Off by default — turn on and paste URLs.

## `jobUrls` (type: `array`):

CWJobs job page URLs to collect (only used when Scrape by URL is enabled).

## `webhookUrl` (type: `string`):

Optional. Every record is always saved to the run's dataset — this webhook is an ADDITIONAL real-time push. When set, each new record is also delivered to this URL (CRM, Slack incoming webhook, Zapier, Make, Google Sheets).

## `webhookFormat` (type: `string`):

Payload format for the webhook push: raw JSON record, or a Slack-friendly message.

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

Proxy for CWJobs collection. Residential GB proxies are recommended for the freshest UK results.

## Actor input object example

```json
{
  "enableJobSearch": true,
  "jobKeywords": [
    "software engineer"
  ],
  "jobLocation": "London",
  "jobsPerQuery": 10,
  "fetchFullDetails": false,
  "enableCompanyJobs": false,
  "companyNames": [],
  "jobsPerCompany": 10,
  "enableScrapeByUrl": false,
  "jobUrls": [],
  "webhookUrl": "",
  "webhookFormat": "json",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "GB"
  }
}
```

# Actor output Schema

## `allResults` (type: `string`):

Complete dataset with every job field from all enabled features in this run.

## `jobs` (type: `string`):

Job rows from job search, company jobs, and scrape-by-URL.

## `runSummary` (type: `string`):

Per-run metadata: enabled features, exported record count, non-fatal errors, spending-limit status, and the paywall object (detected, isPaying, pricingTier, blocked, limited).

# 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 = {
    "enableJobSearch": true,
    "jobKeywords": [
        "software engineer"
    ],
    "jobLocation": "London",
    "jobsPerQuery": 10,
    "fetchFullDetails": false,
    "enableCompanyJobs": false,
    "jobsPerCompany": 10,
    "enableScrapeByUrl": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("b2b_leads/cwjobs-real-time-data-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 = {
    "enableJobSearch": True,
    "jobKeywords": ["software engineer"],
    "jobLocation": "London",
    "jobsPerQuery": 10,
    "fetchFullDetails": False,
    "enableCompanyJobs": False,
    "jobsPerCompany": 10,
    "enableScrapeByUrl": False,
}

# Run the Actor and wait for it to finish
run = client.actor("b2b_leads/cwjobs-real-time-data-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 '{
  "enableJobSearch": true,
  "jobKeywords": [
    "software engineer"
  ],
  "jobLocation": "London",
  "jobsPerQuery": 10,
  "fetchFullDetails": false,
  "enableCompanyJobs": false,
  "jobsPerCompany": 10,
  "enableScrapeByUrl": false
}' |
apify call b2b_leads/cwjobs-real-time-data-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,b2b_leads/cwjobs-real-time-data-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/OkavtGLQCaeu8UgdJ/builds/4IVEu3opBv5SE3w8D/openapi.json
