# France Travail Scraper — Scrape Job Offers from Pôle Emploi (`apikiy/france-travail-scraper`) Actor

An [Apify actor](https://apify.com/) that scrapes job listings from [France Travail](https://candidat.francetravail.fr/) (formerly Pôle Emploi) using Playwright

- **URL**: https://apify.com/apikiy/france-travail-scraper.md
- **Developed by:** [Julien ApiKiy](https://apify.com/apikiy) (community)
- **Categories:** Jobs
- **Stats:** 2 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

## France Travail Job Scraper

An [Apify actor](https://apify.com/) that scrapes job listings from [France Travail](https://candidat.francetravail.fr/) (formerly Pôle Emploi) using Playwright with anti-detection measures.

### Features

- 🔍 Search jobs by keyword, location, and contract type
- 📄 Multi-page pagination with configurable depth
- 🛡️ Anti-detection: random user agents, delays, webdriver override
- 💰 Optional detail page visits for salary and full description extraction
- 🇫🇷 French market focus — defaults to all of France
- 📊 Deduplication across pages and queries
- ⚙️ Configurable concurrency, delays, and result limits

### Usage

#### On Apify Platform

1. Go to the actor's page on Apify Console
2. Set the input — at minimum provide `searchQueries`:

```json
{
  "searchQueries": ["développeur react", "ingénieur python"],
  "locations": ["Paris", "Lyon"],
  "contractTypes": ["CDI"],
  "maxResults": 50,
  "maxPages": 5,
  "visitDetails": false
}
````

3. Click **Start** and wait for results in the dataset.

#### Run Locally

```bash
## Install dependencies
npm install

## Run with Apify local APIFIFY_TOKEN
APIFY_TOKEN=your_token npm start

## Or provide input via stdin
echo '{"searchQueries": ["développeur web"], "maxResults": 10}' | npm start
```

#### Run via Docker

```bash
docker build -t france-travail-scraper .
docker run -e APIFY_TOKEN=your_token france-travail-scraper
```

### Input

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `searchQueries` | `string[]` | *required* | Job titles, keywords, or skills (e.g., `"comptable"`, `"infirmier"`) |
| `locations` | `string[]` | `[]` (all France) | Cities, departments, or regions (e.g., `"Paris"`, `"75"`) |
| `contractTypes` | `string[]` | `[]` (all) | Filter: `CDI`, `CDD`, `Interimaire`, `Stage`, `Apprentissage` |
| `maxResults` | `number` | `20` | Maximum total job listings to collect (1–200) |
| `maxPages` | `number` | `5` | Max search result pages per query (1–20) |
| `visitDetails` | `boolean` | `false` | Visit each job's detail page for salary/full description |
| `delayMin` | `number` | `2000` | Minimum delay between requests (ms) |
| `delayMax` | `number` | `5000` | Maximum delay between requests (ms) |
| `maxConcurrency` | `number` | `1` | Concurrent browser pages (keep ≤2 to avoid detection) |
| `debugMode` | `boolean` | `false` | Enable verbose logging |

### Output

Each job listing contains:

```json
{
  "jobId": "210SSZN",
  "title": "Développeur Web Full Stack",
  "company": "ACME Corp",
  "location": "75 - Paris",
  "contractType": "CDI",
  "salary": "Annuel de 35000.0 Euros à 40000.0 Euros",
  "publicationDate": "Publié hier",
  "description": "Nous recherchons un développeur web...",
  "url": "https://candidat.francetravail.fr/offres/recherche/detail/210SSZN",
  "searchQuery": "développeur web",
  "scrapedAt": "2025-01-15T10:30:00.000Z"
}
```

### Development

```bash
## Install dev dependencies
npm install

## Run tests
npm test

## Watch mode
npm run test:watch
```

### How It Works

1. Builds search URLs for each query × location combination with pagination
2. Launches a headless Chromium browser with anti-detection flags
3. Navigates to France Travail search results pages
4. Extracts job listings from the DOM (title, company, location, contract, URL)
5. Optionally visits detail pages to get salary and full descriptions
6. Deduplicates by job ID and pushes results to the Apify dataset

### Anti-Detection Measures

- Random user agent rotation (8 Chrome/Firefox/Safari agents)
- Configurable random delays between requests (default 2–5s)
- `navigator.webdriver` override to hide automation
- Fake `navigator.plugins` and French language preferences
- Chromium flags: `--disable-blink-features=AutomationControlled`, `--lang=fr-FR`
- Cookie consent banner auto-dismissal

### 💰 Pricing

Pay-per-use, no monthly fees:

| | Price |
|---|---|
| **Actor start** | $0.01 |
| **Per result** | $0.01 |

> 💡 Example: A run returning 500 results costs **$5.01** total ($0.01 start + 500 × $0.01).

### License

ISC

# Actor input Schema

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

Job titles, keywords, or skill sets to search for (e.g., 'développeur', 'comptable', 'infirmier')

## `locations` (type: `array`):

Cities, departments, or regions to search in (e.g., 'Paris', 'Lyon', '75'). Leave empty for all France.

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

Filter by contract type

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

Maximum number of job listings to scrape total

## `maxPages` (type: `integer`):

Maximum number of search result pages to scrape per query

## `visitDetails` (type: `boolean`):

Visit each job's detail page to extract salary and full description (slower but more complete)

## `delayMin` (type: `integer`):

Minimum delay between requests in milliseconds

## `delayMax` (type: `integer`):

Maximum delay between requests in milliseconds

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

Number of concurrent browser pages (keep low to avoid detection)

## `debugMode` (type: `boolean`):

Enable verbose logging for debugging

## Actor input object example

```json
{
  "searchQueries": [
    "développeur"
  ],
  "contractTypes": [
    "CDI"
  ],
  "maxResults": 20,
  "maxPages": 5,
  "visitDetails": false,
  "delayMin": 2000,
  "delayMax": 5000,
  "maxConcurrency": 1,
  "debugMode": 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 = {
    "searchQueries": [
        "développeur"
    ],
    "contractTypes": [
        "CDI"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("apikiy/france-travail-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": ["développeur"],
    "contractTypes": ["CDI"],
}

# Run the Actor and wait for it to finish
run = client.actor("apikiy/france-travail-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 '{
  "searchQueries": [
    "développeur"
  ],
  "contractTypes": [
    "CDI"
  ]
}' |
apify call apikiy/france-travail-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "France Travail Scraper — Scrape Job Offers from Pôle Emploi",
        "description": "An [Apify actor](https://apify.com/) that scrapes job listings from [France Travail](https://candidat.francetravail.fr/) (formerly Pôle Emploi) using Playwright",
        "version": "0.1",
        "x-build-id": "jKCnKi4YaALV9Xr9x"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/apikiy~france-travail-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-apikiy-france-travail-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/apikiy~france-travail-scraper/runs": {
            "post": {
                "operationId": "runs-sync-apikiy-france-travail-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/apikiy~france-travail-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-apikiy-france-travail-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "searchQueries": {
                        "title": "Search Queries",
                        "type": "array",
                        "description": "Job titles, keywords, or skill sets to search for (e.g., 'développeur', 'comptable', 'infirmier')",
                        "default": [
                            "développeur"
                        ],
                        "items": {
                            "type": "string"
                        }
                    },
                    "locations": {
                        "title": "Locations",
                        "type": "array",
                        "description": "Cities, departments, or regions to search in (e.g., 'Paris', 'Lyon', '75'). Leave empty for all France.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "contractTypes": {
                        "title": "Contract Types",
                        "type": "array",
                        "description": "Filter by contract type",
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxResults": {
                        "title": "Max Results",
                        "minimum": 1,
                        "maximum": 200,
                        "type": "integer",
                        "description": "Maximum number of job listings to scrape total",
                        "default": 20
                    },
                    "maxPages": {
                        "title": "Max Pages",
                        "minimum": 1,
                        "maximum": 20,
                        "type": "integer",
                        "description": "Maximum number of search result pages to scrape per query",
                        "default": 5
                    },
                    "visitDetails": {
                        "title": "Visit Job Detail Pages",
                        "type": "boolean",
                        "description": "Visit each job's detail page to extract salary and full description (slower but more complete)",
                        "default": false
                    },
                    "delayMin": {
                        "title": "Min Delay (ms)",
                        "type": "integer",
                        "description": "Minimum delay between requests in milliseconds",
                        "default": 2000
                    },
                    "delayMax": {
                        "title": "Max Delay (ms)",
                        "type": "integer",
                        "description": "Maximum delay between requests in milliseconds",
                        "default": 5000
                    },
                    "maxConcurrency": {
                        "title": "Max Concurrency",
                        "type": "integer",
                        "description": "Number of concurrent browser pages (keep low to avoid detection)",
                        "default": 1
                    },
                    "debugMode": {
                        "title": "Debug Mode",
                        "type": "boolean",
                        "description": "Enable verbose logging for debugging",
                        "default": false
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
