# Jobbird Jobs Scraper (`steadyscrape/jobbird-jobs-scraper`) Actor

Scrape Jobbird job listings (jobbird.com, Netherlands and UK) by job title and place: title, employer, town, salary, hours, education level, posted date, full description, contract type and apply link. Only-new-jobs mode for daily feeds. Export to JSON, CSV or Excel, or via API.

- **URL**: https://apify.com/steadyscrape/jobbird-jobs-scraper.md
- **Developed by:** [Steady Scrape](https://apify.com/steadyscrape) (community)
- **Categories:** Jobs, Lead generation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 jobs

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

## Jobbird Jobs Scraper

Scrape job listings from **[Jobbird](https://www.jobbird.com)**, the Dutch job board (with its UK site), by **job title**
and **place**. This Jobbird scraper gives every vacancy with its **employer**, **town and distance from the place you
searched**, **salary as numbers**, **working hours**, **education level**, **posted date**, logo and link — and, from each
job's own page, the **full description**, **occupation group**, **contract type**, **employment type**, **education and
languages asked**, whether the **employer recruits itself**, the **employer's website**, the **apply link** and the
**address**.

No start fee, no login. Pay only for the jobs you get; searches that find nothing cost nothing.

> This Actor is unofficial and is not affiliated with, endorsed by or connected to Jobbird, Jobster Media or YoungCapital.

### What you can do with this Jobbird scraper

- **Recruiting and sourcing in the Netherlands**: every open vacancy (vacature) for a job title in Utrecht, Amsterdam,
  Rotterdam or any town, with the employer or agency advertising it.
- **Salary and hours benchmarking**: published pay ranges and weekly hours as numbers, by job title and town.
- **Job alerts and feeds**: schedule it daily with **Posted within** and **Only new jobs** to receive just the vacancies
  posted since the last run — into a spreadsheet, Slack, email or your ATS through Apify's integrations.
- **Lead generation for recruitment agencies and HR services**: who is hiring for what, where, and whether they recruit
  themselves.
- **Labour-market research**: demand by occupation, town and province, part-time vs full-time, education levels.

### How the Jobbird search works

Jobbird's free-text search is closed to crawlers by its robots.txt, so this Actor reads **Jobbird's own lists**, which are
the same pages you reach by clicking a town or a job title on the site:

- **A job title in a place** — `developer` in `Utrecht` reads `jobbird.com/nl/vacatures/utrecht/developer`.
- **A job title alone** — `verpleegkundige` reads the national list `jobbird.com/nl/beroepsgroep/zorg-medisch/verpleegkundige`.
- **An occupation group** — `ICT`, `Zorg en medisch`, `Logistiek`: alone or in a place.
- **A place alone** — every vacancy in a town, a province (`Noord-Holland`) or the whole country (`Nederland`).

Jobbird has lists for about 1,100 Dutch job titles. A title it has no list for is read through the **nearest** one it
has (`senior java developer` → java developer; the search label says which). Add **Title must contain** to narrow any
list to the titles you want, e.g. the Gouda list with `developer`.

### Input

| Field | What it does |
|---|---|
| **Jobbird site** | Netherlands (default) or United Kingdom. |
| **Job titles or occupation groups** | `developer`, `verpleegkundige`, `accountant`, `chauffeur`, `ICT`… Each is searched in each place, or across the country without places. |
| **Places** | `Utrecht`, `Den Haag`, `Amsterdam`, `Noord-Holland`, `provincie Utrecht`, `Nederland`; on the UK site `London`, `Manchester`, `Scotland`, `UK`. Jobbird's place lists take in jobs up to about 30 km away. |
| **Jobbird list links** | Lists copied from Jobbird (`/nl/vacatures/…`, `/nl/beroepsgroep/…`, `/uk/jobs/…`), read from their first page. |
| **Title must contain** | Keep only jobs whose title contains one of these words (case, accents and hyphens ignored). |
| **Maximum distance (km)** | Leave out jobs listed farther from the place than this; 0 keeps the town itself. |
| **Posted within** | Last 24 hours, 3, 7, 14 or 30 days. |
| **Only jobs with a salary** | Leaves out ads without a salary. |
| **Include job details** | On by default: opens each job's page (charged as job-with-details). |
| **Max jobs per search** | 100 by default; 0 for every job the list shows. |
| **Only new jobs since the last run** | Monitor mode for scheduled runs: jobs delivered before are skipped and not charged. |

Example — developers in Utrecht and Amsterdam posted this week, within 15 km:

```json
{
    "jobTitles": ["developer", "software engineer"],
    "places": ["Utrecht", "Amsterdam"],
    "postedWithin": "7",
    "maxDistanceKm": 15,
    "maxJobsPerSearch": 200
}
```

Example — every nursing vacancy in the Netherlands, as a daily feed of new ones:

```json
{
    "jobTitles": ["verpleegkundige", "wijkverpleegkundige"],
    "onlyNewJobs": true,
    "maxJobsPerSearch": 0
}
```

Example — UK: data jobs in London.

```json
{
    "country": "uk",
    "places": ["London"],
    "titleFilter": ["data analyst", "data engineer", "data scientist"],
    "maxJobsPerSearch": 0
}
```

### Output

One row per job (with job details on):

```json
{
    "jobId": "26108645",
    "url": "https://www.jobbird.com/nl/vacature/26108645-teammanager-ouderenzorg-pg-n-berkenstede-n-diemen",
    "title": "Teammanager ouderenzorg PG – Berkenstede – Diemen",
    "companyName": "Cordaan",
    "companyId": "25589",
    "companyLogo": "https://res.cloudinary.com/hippo-hr/image/upload/s--tZ4diIGi--/c_lpad,h_200,w_200/f_png/q_auto:best/v1/jobbird/nl_nl/recruiterlogos/jixmecwikk1xgkchzjho.jpg?_a=BAAHWXH8",
    "place": "Diemen",
    "placeUrl": "https://www.jobbird.com/nl/vacatures/diemen",
    "distanceKm": 6.3,
    "salaryMin": 3772,
    "salaryMax": 5413,
    "salaryCurrency": "EUR",
    "hoursMin": 32,
    "hoursMax": 36,
    "hoursText": "32 - 36. Een jaarcontract voor 32 – 36 uur per week met uitzicht op een vast contract",
    "workingTime": "full-time",
    "educationMin": "HBO",
    "educationMax": "HBO",
    "educationRequired": false,
    "postedAt": "2026-10-16T19:12:24.000Z",
    "isPremium": false,
    "rowType": "job",
    "status": "ok",
    "search": "verpleegkundige · Amsterdam",
    "scrapedAt": "2026-10-31T07:20:00.000Z",
    "searchUrl": "https://www.jobbird.com/nl/vacatures/amsterdam/verpleegkundige",
    "position": 1,
    "details": {
        "description": "Omschrijving\nWij zijn voor onze woonlocatie Berkenstede in Diemen op zoek naar een teammanager die eindverantwoordelijk is voor de kwaliteit van de zorg die gel…",
        "descriptionHtml": "Omschrijving<p><em>Wij zijn voor onze woonlocatie Berkenstede in Diemen op zoek naar een t…",
        "category": "Zorg en medisch",
        "contractTypes": [
            "fulltime"
        ],
        "employmentTypes": [
            "FULL_TIME"
        ],
        "educationLevels": [
            "HBO"
        ],
        "educationText": "hbo-diploma in de zorg en hbo-management diploma",
        "languages": [
            {
                "language": "Dutch",
                "required": true
            }
        ],
        "recruitmentType": null,
        "employerDescription": null,
        "employerWebsite": "www.cordaanthuisdiensten.nl",
        "applyUrl": "https://werkenbijcordaan.nl/o/teammanager-ouderenzorg-pg-berkenstede-diemen/?utm_medium=referral&utm_source=Jobbird&utm_campaign=Jobbird&utm_content=apply",
        "directApply": false,
        "streetAddress": null,
        "addressLocality": "DIEMEN",
        "addressRegion": "Diemen",
        "addressCountry": "NL"
    }
}
```

A search that gives nothing to charge for gives one **free** row with the reason: `no_results` (no job, or every job left
out by your filters, counted by filter), `not_found` (a title, place or list Jobbird has no list for, with what to try
instead), `invalid` (a link that is not a Jobbird list), `disallowed` (a list Jobbird's robots.txt closes to crawlers) or
`blocked` (Jobbird stopped answering). The run's **SUMMARY** record lists, per search, the Jobbird list read, the jobs
found, listed and left out by each filter, and the place and title the list said it shows.

#### Fields

| Field | Description |
|---|---|
| `jobId`, `url`, `title` | Jobbird's job id, the job's page and its title. |
| `companyName`, `companyId`, `companyLogo` | The employer or agency advertising the job (some agencies advertise as "Uitzendbureau"). |
| `place`, `placeUrl`, `distanceKm` | The job's town, its Jobbird list, and its distance in km from the place you searched (`null` on lists without a place). |
| `salaryMin`, `salaryMax`, `salaryCurrency` | The salary range the ad gives, in EUR or GBP. Jobbird publishes the amounts without their period: a Dutch salary is usually per month, a UK one per year, a contractor's per day or hour. |
| `hoursMin`, `hoursMax`, `hoursText`, `workingTime` | Weekly hours as numbers and as written, and `full-time`, `part-time` or `full-or-part-time`. |
| `educationMin`, `educationMax`, `educationRequired` | Jobbird's education levels (MBO, HBO, WO…) and whether the level is required. |
| `postedAt`, `isPremium` | When the ad was posted or last refreshed (ISO 8601, UTC), and whether it is a paid placement. |
| `rowType`, `status`, `reason` | `job` rows carry status `ok`; a free `status` row carries `no_results`, `not_found`, `invalid`, `disallowed` or `blocked`, the `url` it is about and the `reason` in words. |
| `search`, `searchUrl`, `position`, `scrapedAt` | Which search found the job, the list it came from, its place in that search, and when. |
| `details.description`, `details.descriptionHtml` | The full job description as text and as HTML. |
| `details.category`, `details.contractTypes`, `details.employmentTypes` | Jobbird's occupation group ("ICT"), its contract types ("fulltime", "Tijdelijk werk", "Permanent"…) and the schema.org employment types. |
| `details.educationLevels`, `details.educationText`, `details.languages` | The education asked, as levels and in the ad's words, and the languages asked. |
| `details.recruitmentType` | "Intern" when the employer recruits itself; empty otherwise. |
| `details.employerDescription`, `details.employerWebsite` | The employer's own text and website, when the ad gives them. |
| `details.applyUrl`, `details.directApply` | Where you apply (often the employer's or another job site's page, through a tracking link), and the direct-apply flag as Jobbird's own job posting sets it. |
| `details.streetAddress`, `addressLocality`, `addressRegion`, `addressCountry` | The job's address as the ad gives it. |

### Pricing

Pay per event, no start fee:

| Event | Price |
|---|---|
| `job` — a job as its list card shows it | US$0.001 |
| `job-with-details` — a job with its own page read | US$0.002 |

Rows with a reason (no results, not found, invalid, disallowed, blocked) and jobs already delivered earlier in the run are
free. Set a maximum cost per run in Apify and the Actor stops at it.

### Limits

- The Actor follows Jobbird's **robots.txt**: it reads Jobbird's place, job-title and group lists and the job pages, never
  its free-text search, so **Posted within**, **Title must contain**, **distance** and **salary** are applied by the
  Actor to the jobs it reads.
- Jobbird has job-title lists for the larger towns only, and none for provinces: those searches give a free row saying so,
  and the place alone with **Title must contain** reads them instead.
- Jobbird lets a list be browsed 500 pages (7,500 jobs) deep; Amsterdam's and London's whole lists are longer.
- The UK site has industries (`IT, Software, Technology`, `Healthcare, Nursing, Medical`…) but no job-title lists: use
  places with **Title must contain** there. Jobbird's German site is not read.
- Salary amounts come without their period (see the fields). Recruiters' names, emails and phone numbers are not
  collected as fields; some ads name a contact inside their description.

### Is it legal to scrape Jobbird?

This Actor reads public job listings that anyone can see without an account, follows Jobbird's robots.txt, and asks for
one page a second. It collects no personal data as fields. Check that your use of the data complies with Jobbird's terms
and with the GDPR and other laws that apply to you. This Actor is unofficial and not affiliated with Jobbird, Jobster
Media or YoungCapital.

# Actor input Schema

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

Jobbird's Dutch site (jobbird.com/nl, the big one) or its British one (jobbird.com/uk).

## `jobTitles` (type: `array`):

As Jobbird names them, e.g. <code>developer</code>, <code>verpleegkundige</code>, <code>accountant</code>, <code>chauffeur</code>, or a group such as <code>ICT</code> or <code>Zorg en medisch</code>. Each is read through Jobbird's own list for it; a title Jobbird has no list for is read through the nearest one it has ("senior java developer" → java developer, named in the search), or gives a free row naming close ones. The UK site has industries only (<code>IT, Software, Technology</code>): use places with the title filter there. Leave empty to read the places' whole lists.

## `places` (type: `array`):

Towns as Jobbird writes them (<code>Utrecht</code>, <code>Den Haag</code>, <code>London</code>), a Dutch province (<code>Noord-Holland</code>, <code>provincie Utrecht</code>), <code>Nederland</code>, or a UK country (<code>Scotland</code>, <code>UK</code>). Jobbird's place lists take in jobs up to about 30 km away; each job carries its distance. Leave empty to search the job titles across the country. Jobbird has no job-title lists for provinces, and only for the larger towns: those give a free row saying so.

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

Lists copied from Jobbird, e.g. <code>https://www.jobbird.com/nl/vacatures/utrecht/developer</code> or <code>https://www.jobbird.com/nl/beroepsgroep/ict</code>, each read from its first page. Jobbird's free-text search (<code>/nl/vacature?s=…</code>) is closed to crawlers by its robots.txt and is not taken, nor are job pages.

## `titleFilter` (type: `array`):

Keep only jobs whose title contains one of these words or phrases (case, accents and hyphens ignored), e.g. <code>senior</code>, <code>java</code>, <code>front-end</code>. Applied by the Actor to every list it reads.

## `maxDistanceKm` (type: `integer`):

Leave out jobs Jobbird lists farther than this from the place searched. 0 keeps the town itself only.

## `postedWithin` (type: `string`):

Only jobs posted or refreshed in the last days. Combine with a schedule and Only new jobs for a daily feed.

## `onlyWithSalary` (type: `boolean`):

Leave out jobs whose ad gives no salary.

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

Open each job's page for the full description, occupation group, contract type, employment type, education asked, languages, whether the employer recruits itself, the employer's website, the apply link and the address. Charged as job-with-details instead of job.

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

Stop each search (each job title in each place, and each link) after this many jobs. 0 means every job the list shows (Jobbird lets a list be browsed 7,500 jobs deep).

## `onlyNewJobs` (type: `boolean`):

Deliver, and charge, only jobs that an earlier run with the same searches and filters has not delivered. Made for scheduled runs.

## Actor input object example

```json
{
  "country": "nl",
  "jobTitles": [
    "developer"
  ],
  "places": [
    "Utrecht"
  ],
  "searchUrls": [],
  "titleFilter": [],
  "postedWithin": "any",
  "onlyWithSalary": false,
  "includeDetails": true,
  "maxJobsPerSearch": 2,
  "onlyNewJobs": false
}
```

# Actor output Schema

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

No description

## `summary` (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 = {
    "jobTitles": [
        "developer"
    ],
    "places": [
        "Utrecht"
    ],
    "maxJobsPerSearch": 2
};

// Run the Actor and wait for it to finish
const run = await client.actor("steadyscrape/jobbird-jobs-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 = {
    "jobTitles": ["developer"],
    "places": ["Utrecht"],
    "maxJobsPerSearch": 2,
}

# Run the Actor and wait for it to finish
run = client.actor("steadyscrape/jobbird-jobs-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 '{
  "jobTitles": [
    "developer"
  ],
  "places": [
    "Utrecht"
  ],
  "maxJobsPerSearch": 2
}' |
apify call steadyscrape/jobbird-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,steadyscrape/jobbird-jobs-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/S0zKrG8i4h32uZrL9/builds/M4yhlBXl6nDaM84SR/openapi.json
