# Adzuna Jobs Scraper (`solidcode/adzuna-scraper`) Actor

\[💰 $0.55 / 1K] Extract job listings from Adzuna across 19 countries. Search by keyword, location, salary, contract type, and distance to get structured data including titles, companies, salaries, descriptions, categories, and direct apply links.

- **URL**: https://apify.com/solidcode/adzuna-scraper.md
- **Developed by:** [SolidCode](https://apify.com/solidcode) (community)
- **Categories:** Jobs, Automation, Developer tools
- **Stats:** 3 total users, 3 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-usage

## 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

## Adzuna Jobs Scraper

Pull job listings from Adzuna at scale — titles, companies, native salary ranges, full descriptions, contract terms, categories, geo coordinates, and direct apply links across 19 country markets. Built for recruiters, labor-market analysts, and job-board aggregators who need clean, structured Adzuna data without copying postings by hand or babysitting a brittle in-house scraper.

### Why This Scraper?

- **19 country markets in one actor** — United States, United Kingdom, Germany, France, Australia, Canada, India, Netherlands, Italy, Spain, Switzerland, and 8 more, each returning salaries in its own local currency.
- **Clean numeric salary min/max, not just a text blob** — every row carries `salaryMin` and `salaryMax` as real numbers alongside the original `salary` text, so salary benchmarking and sorting just work. A `salaryIsPredicted` flag tells you when a figure is Adzuna's own estimate versus an advertised wage.
- **Full-text job descriptions, not truncated snippets** — flip `fetchDescription` on and every row carries the complete posting text pulled from the listing's detail page, not the one-line search-result teaser most scrapers stop at.
- **Seven native Adzuna filters wired in** — salary range, full-time vs. part-time, permanent vs. contract, distance radius in miles, posted-within window (24 hours to 30 days), and sort by relevance, date, or highest salary.
- **Geo coordinates on every job** — `latitude` and `longitude` for each listing, ready to drop onto a map or join against your own location data.
- **ISO-8601 dates you can sort and diff** — `postedDate` and `validThrough` as clean timestamps, plus the job `category` and a stable `jobId` for de-duplication across runs.
- **Three ways to search** — keyword queries, a city plus a mileage radius, or paste fully-filtered Adzuna search URLs straight from your browser. Mix all three in a single run.
- **Up to 1,000 jobs per keyword, auto-deduplicated** — batch up to 50 keywords per run; overlapping searches never produce duplicate rows.

### Use Cases

**Recruitment & Talent Sourcing**

- Build live feeds of open roles by title, city, and radius
- Track which companies are hiring for a given skill in a target market
- Surface direct apply links for fast candidate outreach
- Monitor new postings in the last 24 hours for hard-to-fill roles

**Labor-Market & Economic Research**

- Measure hiring demand by category and region across 19 countries
- Compare full-time vs. contract volume in a sector over time
- Map openings geographically using per-job coordinates
- Quantify how long roles stay live using posted and expiry dates

**Salary Benchmarking & Compensation**

- Pull numeric salary ranges to benchmark pay by role and location
- Separate advertised salaries from Adzuna's predicted figures
- Compare compensation across countries in local currency
- Build percentile bands for offer and pay-equity analysis

**Job-Board & Aggregator Feeds**

- Power a niche job board with fresh, structured listings
- Enrich existing postings with full descriptions and categories
- Keep an alerting system fed with newest-first results
- Re-run filtered Adzuna search URLs on a schedule to stay current

**Sales & Lead Generation**

- Identify companies actively scaling a particular team
- Target outreach by hiring signals in a specific city or sector
- Feed hiring data into a CRM as a growth indicator

### Getting Started

#### Simple Keyword Search

The minimum input — one keyword in one country:

```json
{
    "searchQueries": ["software engineer"],
    "country": "us",
    "maxResults": 100
}
```

#### Filtered Search — Location, Salary, and Recency

Senior full-time roles near a city, paying at least a threshold, posted recently:

```json
{
    "searchQueries": ["data scientist"],
    "country": "gb",
    "location": "London",
    "distance": 25,
    "salaryMin": 60000,
    "contractTime": "full_time",
    "contractType": "permanent",
    "maxDaysOld": "7",
    "sortBy": "date",
    "maxResults": 250
}
```

#### Advanced — Paste Adzuna Search URLs

Dial in a search on the Adzuna website, then paste the URLs to scrape them exactly as-is:

```json
{
    "startUrls": [
        "https://www.adzuna.com/search?q=product+manager&w=New+York",
        "https://www.adzuna.de/search?q=software+entwickler"
    ],
    "fetchDescription": true,
    "maxResults": 500
}
```

### Input Reference

#### Search

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `searchQueries` | string\[] | `["software engineer"]` | Job titles or keywords. Each keyword runs a separate search; results are merged and de-duplicated. Up to 50 per run. |
| `country` | select | `United States` | Adzuna market to search. Salaries are returned in that country's local currency. 19 countries supported. |
| `location` | string | `""` | City or region within the chosen country (e.g. "London", "New York"). Leave empty to search the whole country. |
| `startUrls` | string\[] | `[]` | Full Adzuna search-result URLs to scrape exactly as-is. Useful when you have already dialed in a search on the website. Up to 50 URLs. |

#### Filters & Limits

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `maxResults` | integer | `100` | Maximum jobs to collect per keyword (1–1,000). The last page is kept in full, so the final count can slightly overshoot. |
| `salaryMin` | integer | — | Only show jobs paying at least this much per year, in local currency. |
| `salaryMax` | integer | — | Only show jobs paying at most this much per year, in local currency. |
| `contractTime` | select | `Any` | Working hours: Any, Full-time, or Part-time. |
| `contractType` | select | `Any` | Contract arrangement: Any, Permanent, or Contract. |
| `distance` | integer | — | Search radius from the location, in miles (1–500). Ignored when location is empty. |
| `maxDaysOld` | select | `Any time` | Posted-within window: Any time, Last 24 hours, Last 3 days, Last 7 days, Last 14 days, or Last 30 days. |
| `sortBy` | select | `Most relevant` | Result order: Most relevant, Newest first, or Highest salary first. |

#### Advanced

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `fetchDescription` | boolean | `true` | Fetch the full job description from each listing's detail page. Leave on for the most complete data; turn off for faster runs (the description field then holds only the search-result snippet). |

### Output

Each record is one job listing. Here is a representative result with full descriptions enabled:

```json
{
    "title": "Senior Software Engineer",
    "company": "Acme Technologies",
    "location": "New York, NY",
    "locationAreas": ["US", "New York", "New York City"],
    "salary": "$140,000 - $180,000",
    "salaryMin": 140000,
    "salaryMax": 180000,
    "salaryIsPredicted": false,
    "salaryCurrency": "USD",
    "contractTime": "full_time",
    "contractType": "permanent",
    "category": "IT Jobs",
    "descriptionSnippet": "We are hiring a Senior Software Engineer to lead our platform team...",
    "description": "We are hiring a Senior Software Engineer to lead our platform team. You will design and ship backend services, mentor engineers, and own delivery end to end...",
    "postedDate": "2026-05-21T09:00:00Z",
    "validThrough": "2026-06-20T09:00:00Z",
    "latitude": 40.7128,
    "longitude": -74.006,
    "jobUrl": "https://www.adzuna.com/details/4567890123",
    "jobId": "4567890123",
    "country": "us",
    "searchQuery": "software engineer",
    "searchLocation": "New York",
    "scrapedAt": "2026-05-30T14:30:00Z"
}
```

#### Core Fields

| Field | Type | Description |
|-------|------|-------------|
| `title` | string | Job title. |
| `company` | string | Hiring company name. |
| `location` | string | Human-readable location label as shown on Adzuna. |
| `locationAreas` | string\[] | Location broken into a hierarchy (country → region → city). |
| `category` | string | Adzuna job category (e.g. "IT Jobs", "Healthcare & Nursing Jobs"). |
| `descriptionSnippet` | string | Short teaser from the search-result card. |
| `description` | string | Full job description when `fetchDescription` is on; otherwise the snippet. |
| `jobId` | string | Stable Adzuna listing identifier, ideal for de-duplication. |
| `jobUrl` | string | Direct link to the Adzuna listing. |

#### Salary

| Field | Type | Description |
|-------|------|-------------|
| `salary` | string | Salary as displayed on Adzuna, formatted with currency. |
| `salaryMin` | number | Lower bound of the salary range, native numeric value. |
| `salaryMax` | number | Upper bound of the salary range, native numeric value. |
| `salaryIsPredicted` | boolean | `true` when the figure is Adzuna's estimate rather than advertised. |
| `salaryCurrency` | string | ISO currency code for the salary (e.g. "USD", "GBP", "EUR"). |
| `contractTime` | string | `full_time` or `part_time` when stated by the listing. |
| `contractType` | string | `permanent` or `contract` when filtered for. |

#### Location & Timing

| Field | Type | Description |
|-------|------|-------------|
| `latitude` | number | Listing latitude. |
| `longitude` | number | Listing longitude. |
| `postedDate` | string | ISO-8601 date the job was posted. |
| `validThrough` | string | ISO-8601 date the listing expires, when published. |

#### Run Metadata

| Field | Type | Description |
|-------|------|-------------|
| `country` | string | Adzuna country code the result came from (e.g. "us", "gb"). |
| `searchQuery` | string | The keyword that produced this row (null for start-URL results). |
| `searchLocation` | string | The location filter used for this row. |
| `scrapedAt` | string | ISO-8601 timestamp of when the row was captured. |

### Tips for Best Results

- **Sort by date and run on a schedule** — set `sortBy` to Newest first with `maxDaysOld` of Last 24 hours, then schedule the actor to catch fresh postings within hours of going live.
- **Copy fully-filtered searches as URLs** — tune category, salary, and location filters on the Adzuna site, then paste the resulting URLs into `startUrls` to reproduce that exact search without rebuilding it field by field.
- **Leave `fetchDescription` on for analysis, off for scale** — full descriptions add a request per job; turn it off when you only need titles, companies, salaries, and links for a fast, wide sweep.
- **Sort and filter on `salaryMin` / `salaryMax`, but read the `salary` text for the pay period** — the numeric fields are clean and sortable, while the original `salary` text tells you whether a figure is per year, per day, or per hour (most are annual, but contract roles can be daily). Check `salaryIsPredicted` before treating any figure as an advertised wage.
- **Match `location` with `distance`** — a city plus a mileage radius captures the surrounding commuter belt that a city-only search misses.
- **Batch related titles in one run** — pass several variants ("data scientist", "ml engineer", "data analyst") in `searchQueries`; overlapping results are de-duplicated automatically by `jobId`.
- **Pick the right country** — each market is searched on its own Adzuna domain, so set `country` to the market you actually want rather than relying on a location string alone.

### Pricing

**$0.55 per 1,000 results** — no monthly rental, no tiered plans. You pay only for the job listings you actually receive.

| Results | Estimated Cost |
|---------|----------------|
| 100 | $0.06 |
| 1,000 | $0.55 |
| 10,000 | $5.50 |
| 100,000 | $55.00 |

No compute charges — you only pay per result returned. A "result" is any job row in the output dataset. Platform fees (storage and similar) are additional and depend on your Apify plan.

### Integrations

Export data in JSON, CSV, Excel, XML, or RSS. Connect to 1,500+ apps via:

- **Zapier** / **Make** / **n8n** — Workflow automation
- **Google Sheets** — Direct spreadsheet export
- **Slack** / **Email** — Notifications on new results
- **Webhooks** — Trigger custom APIs when a run completes
- **Apify API** — Full programmatic access

### Legal & Ethical Use

This actor is designed for legitimate recruitment, labor-market research, and salary analysis. Users are responsible for complying with applicable laws and Adzuna's Terms of Service. Do not use collected data for spam, harassment, or any illegal purpose, and respect candidates' and employers' privacy when handling personal data.
</content>
</invoke>

# Actor input Schema

## `searchQueries` (type: `array`):

Job titles or keywords to search for, such as 'software engineer' or 'data scientist'. Each keyword runs a separate search and the results are merged and de-duplicated. Leave empty if you only want to use the direct search URLs below.

## `country` (type: `string`):

Which Adzuna country to search. Salaries are shown in that country's local currency.

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

Where to search within the chosen country. Enter a city or region, such as 'London' or 'New York'. Leave empty to search the whole country.

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

Paste full Adzuna search-result URLs (for example https://www.adzuna.com/search?q=software+engineer) to scrape them exactly as-is. Useful when you have already dialed in a search on the Adzuna website. Up to 50 URLs per run.

## `maxResults` (type: `integer`):

Maximum number of jobs to collect for each search keyword. Use a small number for a quick scan or a higher number for deep research. The last page is always kept in full, so the final count can slightly overshoot this number.

## `salaryMin` (type: `integer`):

Only show jobs paying at least this amount per year, in the chosen country's local currency. Leave empty for any salary.

## `salaryMax` (type: `integer`):

Only show jobs paying at most this amount per year, in the chosen country's local currency. Leave empty for any salary.

## `contractTime` (type: `string`):

Filter by working hours. Leave on 'Any' for both.

## `contractType` (type: `string`):

Filter by contract arrangement. Leave on 'Any' for both.

## `distance` (type: `integer`):

How far from the location to search, in miles. Ignored when the location is empty. Leave empty for the default radius.

## `maxDaysOld` (type: `string`):

Only show jobs posted within this time period.

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

Order in which jobs are returned.

## `fetchDescription` (type: `boolean`):

Fetch the full job description from each listing's detail page. Leave on for the most complete data. Turn off to make runs faster — the description field will then contain only the short search-result snippet.

## Actor input object example

```json
{
  "searchQueries": [
    "software engineer"
  ],
  "country": "us",
  "startUrls": [],
  "maxResults": 100,
  "contractTime": "",
  "contractType": "",
  "maxDaysOld": "",
  "sortBy": "relevance",
  "fetchDescription": true
}
```

# Actor output Schema

## `overview` (type: `string`):

Table of scraped job listings with key fields.

## `detail` (type: `string`):

Complete job data including full descriptions, parsed salary fields, and geo coordinates.

# 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 = {
    "searchQueries": [
        "software engineer"
    ],
    "country": "us",
    "location": "",
    "startUrls": [],
    "maxResults": 100,
    "contractTime": "",
    "contractType": "",
    "maxDaysOld": "",
    "sortBy": "relevance",
    "fetchDescription": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("solidcode/adzuna-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 = {
    "searchQueries": ["software engineer"],
    "country": "us",
    "location": "",
    "startUrls": [],
    "maxResults": 100,
    "contractTime": "",
    "contractType": "",
    "maxDaysOld": "",
    "sortBy": "relevance",
    "fetchDescription": True,
}

# Run the Actor and wait for it to finish
run = client.actor("solidcode/adzuna-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 '{
  "searchQueries": [
    "software engineer"
  ],
  "country": "us",
  "location": "",
  "startUrls": [],
  "maxResults": 100,
  "contractTime": "",
  "contractType": "",
  "maxDaysOld": "",
  "sortBy": "relevance",
  "fetchDescription": true
}' |
apify call solidcode/adzuna-scraper --silent --output-dataset

```

## MCP server setup

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