# Actiris Scraper — Brussels Jobs with Company Numbers (`unfenced-group/actiris-scraper`) Actor

Scrape actiris.brussels — Brussels' official employment service — for structured job data: bilingual FR/NL titles, KBO company numbers, CEFR language requirements, contract details, company descriptions and full listings. 30,000+ active jobs.

- **URL**: https://apify.com/unfenced-group/actiris-scraper.md
- **Developed by:** [Unfenced Group](https://apify.com/unfenced-group) (community)
- **Categories:** Jobs, Developer tools, Automation
- **Stats:** 2 total users, 2 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Actiris Scraper

![Actiris Scraper](https://api.apify.com/v2/key-value-stores/lJlifu6C8YQfZMPKE/records/actiris-scraper)

Extract job listings from actiris.brussels at scale, in a clean, consistent structure ready for analysis, job boards, recruiting tools and market research. No API key required.

***

### Why this scraper?

#### 🎯 Built for Brussels (Belgium)

A dedicated Brussels scraper, not a global tool with a country dropdown. Search, filters and locations are tuned for actiris.brussels.

#### 📄 Complete job data

Bilingual FR/NL titles, full descriptions in text, HTML and Markdown, company registry numbers, contract details and publish dates for every record.

#### 🇧🇪 Structured language requirements

Every job's CEFR language requirements — French, Dutch and more — with comprehension, writing, reading and speaking levels, and whether each language is required or an asset. This is the field that matters most in bilingual Brussels.

#### 🏢 Company registry data

The KBO/BCE company number and a direct link to the official Belgian company register for every listing, plus a verified company logo URL when one exists.

#### 📍 Complete location data

Structured location for every listing. Where the source leaves the municipality blank, it is filled from the postal code, so location is present on every record.

#### 🔁 Change detection

Every record carries a stable content hash and change status, so scheduled feeds return genuinely new jobs instead of duplicates.

***

### Input parameters

| Parameter | Type | Default | Description |
|---|---|---|---|
| `searchQuery` | string | (empty) | Search keyword, e.g. 'developer', 'chauffeur'. Leave blank for all jobs. |
| `postalCodes` | array | (empty) | Filter by Belgian postal code(s), e.g. \["1000", "1050"]. |
| `contractTypes` | array | (empty) | Filter by contract type(s): CDI, CDD, Interim, Freelance, Stage. |
| `imtDomains` | array | (empty) | Filter by Actiris IMT job-family codes. |
| `workTime` | string | (empty) | Filter by work schedule: full-time or part-time. |
| `daysOld` | integer | (empty) | Only return jobs published within the last N days. Leave blank for all. |
| `fetchDetails` | boolean | `false` | ON: fetches full description, company description, candidate profile, benefits, diploma and language requirements. OFF: returns listing-level fields only (faster, lower cost). |
| `descriptionFormat` | string | `all` | Which description format to keep: all, text, html or markdown. |
| `compact` | boolean | `false` | Return core fields only, for AI-agent and MCP pipelines. |
| `excludeEmptyFields` | boolean | `false` | Drop null and empty fields from each record. |
| `maxItems` | integer | `5` | Maximum number of jobs to scrape (0 = no limit). |

***

### Output schema

Listing-level fields are present on every record. Detail-level fields are populated when `fetchDetails` is on and the source publishes them for that job; otherwise they are `null`.

#### Listing-level (always present)

| Field | Type | Description |
|---|---|---|
| `id` | string | Unique listing ID from the source. |
| `url` | string | Direct link to the listing. |
| `applyUrl` | string | Direct link to apply. |
| `title` | string | Job title. |
| `titleNl` | string | Job title in Dutch. |
| `titleFr` | string | Job title in French. |
| `kboNumber` | string | Belgian company registry (KBO/BCE) number. |
| `kboRegistryUrl` | string | Link to the official company register entry. |
| `location` | string | Municipality as displayed. |
| `locationNl` | string | Municipality in Dutch. |
| `locationFr` | string | Municipality in French. |
| `postalCode` | string | Postal code of the position. |
| `country` | string | Country code. |
| `contractType` | string | Contract type in plain English. |
| `contractDuration` | string | Contract duration code (CDI, CDD, etc.). |
| `contractDurationLabel` | string | Contract duration as published. |
| `imtDomain` | string | Actiris IMT job-family code. |
| `typeOffre` | string | Offer type used by the source. |
| `publishDate` | string | Date posted. |
| `modifiedDate` | string | Date last modified. |
| `source` | string | Source domain. |
| `scrapedAt` | string | ISO 8601 scrape timestamp. |
| `contentHash` | string | Stable hash of the listing, used for change detection. |

#### Detail-level (with `fetchDetails` on)

| Field | Type | Description |
|---|---|---|
| `descriptionText` | string | Full job description in plain text. |
| `descriptionHtml` | string | Full job description in HTML. |
| `descriptionMarkdown` | string | Full job description in Markdown. |
| `companyDescription` | string | Description of the employer. |
| `candidateProfile` | string | Required candidate profile. |
| `diploma` | string | Required diploma, when specified. |
| `benefits` | string | Benefits offered, when specified. |
| `additionalInfo` | string | Additional information, when specified. |
| `companyLogo` | string | Verified company logo URL, when one exists. |
| `languageRequirements` | array | Per-language CEFR requirements (see below). |

Each entry in `languageRequirements` contains the `language`, a `required` flag (true = required, false = asset), and `comprehension`, `writing`, `reading` and `speaking` levels.

#### Example record

```json
{
  "id": "5890038",
  "url": "https://www.actiris.brussels/nl/burgers/jobadvertentie/?reference=5890038&type=Select",
  "applyUrl": "https://www.actiris.brussels/nl/burgers/jobadvertentie/?reference=5890038&type=Select",
  "title": "Infirmier breveté ou bachelier H/F/X",
  "titleNl": "Infirmier breveté ou bachelier H/F/X",
  "titleFr": "Infirmier breveté ou bachelier H/F/X",
  "kboNumber": "0239843188",
  "kboRegistryUrl": "https://kbopub.economie.fgov.be/kbopub/toonondernemingps.html?ondernemingsnummer=0239843188",
  "companyLogo": "https://my.actiris.brussels/Repository/Tiers/0239843188/fr.png",
  "location": "Sint-Jans-Molenbeek",
  "locationNl": "Sint-Jans-Molenbeek",
  "locationFr": "Molenbeek-Saint-Jean",
  "postalCode": "1080",
  "country": "BE",
  "contractType": "Permanent",
  "contractDuration": "CDI",
  "contractDurationLabel": "Arbeidsovereenkomst voor onbepaalde duur",
  "imtDomain": "S'6",
  "publishDate": "2026-07-03",
  "modifiedDate": "2026-07-07",
  "companyDescription": "L'employeur est une maison médicale pluridisciplinaire située sur Molenbeek-Saint-Jean.",
  "candidateProfile": "Nous recherchons un infirmier diplômé breveté ou bachelier (H/F/X).",
  "diploma": "Bachelor",
  "benefits": "Contrat CDI Mi-temps. Jours de prestations et horaires à convenir.",
  "languageRequirements": [
    {
      "language": "Frans",
      "required": true,
      "comprehension": "Onafhankelijk + (B2)",
      "writing": "Onafhankelijk + (B2)",
      "reading": "Onafhankelijk + (B2)",
      "speaking": "Onafhankelijk + (B2)"
    },
    {
      "language": "Arabisch",
      "required": false,
      "comprehension": "Onafhankelijk - (B1)",
      "writing": "Geen kennis",
      "reading": "Geen kennis",
      "speaking": "Onafhankelijk - (B1)"
    }
  ],
  "source": "actiris.brussels",
  "scrapedAt": "2026-07-07T10:09:00.000Z",
  "contentHash": "d184329f5857b600"
}
```

***

### Examples

**All nurse roles with full details:**

```json
{
  "searchQuery": "infirmier",
  "fetchDetails": true,
  "maxItems": 100
}
```

**Only jobs from the last 3 days:**

```json
{
  "searchQuery": "vendeur",
  "daysOld": 3,
  "maxItems": 100
}
```

**Compact output for an AI pipeline:**

```json
{
  "searchQuery": "developer",
  "fetchDetails": true,
  "compact": true,
  "descriptionFormat": "markdown",
  "maxItems": 100
}
```

**Daily feed (run on a schedule):**

```json
{
  "daysOld": 1,
  "maxItems": 500
}
```

Schedule this input to run once a day in the Apify Scheduler — each run returns only jobs posted in the last 24 hours.

***

### 💰 Pricing

**$1.50 per 1,000 results** — you only pay for successfully retrieved listings. Failed retries are never charged.

| Results | Cost |
|---|---|
| 100 | ~$0.15 |
| 1,000 | ~$1.50 |
| 10,000 | ~$15 |
| 100,000 | ~$150 |

Subscription tiers lower the rate to $0.90 per 1,000 at the highest tier. Use the **Max results** cap in the input to control spend exactly.

***

### Performance

| Run size | Typical time |
|---|---|
| 100 results | under 1 minute |
| 1,000 results | 2–4 minutes |
| 10,000 results | 20–35 minutes |

Detail fetching adds one request per job, so runs with `fetchDetails` on take longer.

***

### Known limitations

- Actiris does not publish salary, so there are no salary fields.
- Detail-level fields such as company description, benefits and language requirements are returned when the source publishes them for a given job, and are `null` when it does not.
- The employer name is not exposed by the source and is not returned. The company registry number and register link are provided instead.
- Very large result sets are bounded by the source's own paging limits.
- Listings can be removed by the source at any time, so a small share of URLs may expire shortly after scraping.

***

### What we do not collect

This scraper returns company-level and job-level data only. It does not collect recruiter names, personal emails, personal phone numbers or individual contact details. Company registry data and reputation metrics are company-level and are included.

***

### Technical details

- **Source:** actiris.brussels — Brussels (Belgium) job listings
- **Coverage:** everything the public search exposes, filterable via the input parameters above
- **Retry:** automatic retry on network errors with exponential backoff

***

### Need a custom scraper?

**[Unfenced Group](https://www.unfencedgroup.nl)** builds Apify actors for any website — for free.

If the site you need isn't in our portfolio yet, just ask. We scope, build, and publish it at no cost to you. You only pay for results — we absorb the compute and proxy costs ourselves. Same pay-per-result pricing, same quality, same standards as every actor in this portfolio.

**Get in touch:** [www.unfencedgroup.nl](https://www.unfencedgroup.nl)

# Actor input Schema

## `searchQuery` (type: `string`):

Search keyword, e.g. 'developer', 'chauffeur'. Leave blank for all jobs.

## `postalCodes` (type: `array`):

Filter by Belgian postal code(s), e.g. \["1000", "1050"].

## `contractTypes` (type: `array`):

Filter by contract type(s): CDI, CDD, Interim, Freelance, Stage.

## `imtDomains` (type: `array`):

Filter by Actiris IMT job-family codes (e.g. \["T'6"]).

## `workTime` (type: `string`):

Filter by work schedule.

## `daysOld` (type: `integer`):

Only return jobs published within the last N days. Leave blank for all.

## `fetchDetails` (type: `boolean`):

ON: fetches full job description, salary, company info, and all details. OFF: returns basic listing info only (faster, lower cost).

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

Maximum number of jobs to scrape (0 = no limit).

## `descriptionFormat` (type: `string`):

Which description representation to keep. all keeps text/html/markdown; pick one to drop the others.

## `compact` (type: `boolean`):

Return core fields only. Useful for AI-agent and MCP pipelines.

## `excludeEmptyFields` (type: `boolean`):

Drop null, empty-string, and empty-array fields from each record before push.

## Actor input object example

```json
{
  "searchQuery": "developer",
  "postalCodes": [],
  "contractTypes": [],
  "imtDomains": [],
  "workTime": "",
  "fetchDetails": false,
  "maxItems": 100,
  "descriptionFormat": "all",
  "compact": false,
  "excludeEmptyFields": 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 = {
    "searchQuery": "developer",
    "maxItems": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("unfenced-group/actiris-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 = {
    "searchQuery": "developer",
    "maxItems": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("unfenced-group/actiris-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchQuery": "developer",
  "maxItems": 100
}' |
apify call unfenced-group/actiris-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=unfenced-group/actiris-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/Gzvq100FOF13Hoen1/builds/EBnUdJvElYg1boCnZ/openapi.json
