# France Travail Jobs Scraper — French Job Offers & Salaries (`fabrikit/france-travail-jobs-scraper`) Actor

Scrape job offers from France Travail (ex-Pôle emploi) and the partner job boards it lists, by keyword, ROME code, city, department or region. Filter by contract, date, domain, experience and salary; add the full offer with salary, skills and licences. No login. From US$1.05 per 1,000 jobs.

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

## Pricing

from $1.05 / 1,000 job offer scrapeds

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

## France Travail Jobs Scraper — French Job Offers & Salaries

France Travail Jobs Scraper extracts job offers from candidat.francetravail.fr, the job board of France's public employment service (formerly Pôle emploi). That board lists offers posted directly with France Travail and offers from partner job boards such as Meteojob, Beetween, Broadbean, Skello and Cookorico. Search by keyword or ROME occupation code, by city, department, region or the whole country, apply the site's own filters, and download a flat dataset as JSON, CSV or Excel. You don't need an account, a France Travail developer key or cookies.

**Price: US$1.05 per 1,000 job offers.** Full offer records cost an extra US$0.40 per 1,000 if you turn them on.

### What you get

**Search data (every offer, event `job-result`)**

- `jobId`, `url` (the public offer page), `title`, `company` (empty when the employer is anonymous)
- `location` as shown ("69 - Lyon 5e Arrondissement"), split into `departmentCode` and `city`, plus `latitude` / `longitude` when France Travail geocodes the offer
- `contractType` (CDI, CDD, Intérim, …) and `workingTime` (Temps plein / Temps partiel)
- `snippet`: the opening lines of the offer
- `postedText` ("Publié il y a 3 jours"), `postedDaysAgo`, and `postedDate`. The site only shows a relative label, so `postedDate` is that label turned into a Paris calendar date on the day of the run.
- `badges` (for example "Employeur handi-engagé") and `disabilityCommittedEmployer`
- `source` ("France Travail" or the partner board, such as METEOJOB), `isPartnerOffer`, `sourceLogo`
- `searchKeyword`, `searchLocation`, `searchLocationCode`, `searchUrl`, `rank`, `scrapedAt`

**Offer details add-on (`includeDetails: true`, event `job-details`)**

- `description`: the full offer text, with line breaks kept
- `romeCode` and `romeLabel`, the official French occupation code and title
- `salaryText` as published ("Mensuel de 2170.0 Euros à 2175.0 Euros"), parsed into `salaryMin`, `salaryMax`, `salaryPeriod` (month, year, hour), `salaryCurrency`
- `contractSummary`, `contractDuration` ("3 Mois", "38 Jour(s)"), `contractNature`, `schedule` ("35H/semaine", "Travail de nuit"…), `workingHours`, `workConditions`
- `qualification`, `experience`, `experienceRequirement` (beginner-accepted, preferred, required)
- `education`, `skills` and `languages` (each item carries a `required` flag), plus `softSkills`, `drivingLicences` and `benefits`
- Employer facts: `industry`, `companySize`, `companyDescription`, `companyPostalCity`, `companyWebsite`, `employerPageUrl`, `adaptedCompany`
- `disabilityFriendly`, `fewApplicants`, `nationalPrograms` (for example "Plan 1 jeune, 1 solution"), `travel`, `updatedDate` (ISO)

The Actor never asks for recruiter contact details. E-mail addresses, phone numbers, personal profile links and the names of contact persons are removed from every text it saves.

### Use cases

- **Hiring signals for B2B sales:** see which employers in a department are recruiting, for which occupations and contracts, and how large they are.
- **Labour-market and salary studies:** count offers by ROME code, region and contract type; offers that publish a salary give you parsed monthly, yearly or hourly ranges.
- **Job feeds and alerts:** schedule a daily run with `postedWithin: "1"` for a trade and a city, then push new offers to Slack, a sheet or a newsletter.
- **Recruitment and staffing agencies:** watch fixed-term, temp-agency and seasonal demand by place, or follow offers with few applicants.
- **Inclusion programmes:** filter disability-committed employers and adapted companies.

### How to use

1. Add **keywords** (job titles, skills or ROME codes such as `N4101`), or leave them empty to list every offer in a place.
2. Add **places**: a city ("Toulouse"), a department name or number ("Gironde", "33"), a region ("Bretagne") or "France". Each place is looked up with France Travail's own place search. Use **radiusKm** to widen a city search.
3. Pick filters, set `maxItems`, and turn on `includeDetails` if you need full descriptions, salaries and skills.

Full-time truck-driver offers within 30 km of Toulouse, posted directly with France Travail, with full records:

```json
{
  "keywords": ["chauffeur poids lourd"],
  "locations": ["Toulouse"],
  "radiusKm": "30",
  "workingTime": ["full-time"],
  "includePartnerOffers": false,
  "includeDetails": true,
  "maxItems": 100
}
```

Permanent IT jobs for executives in the Paris region, paying at least €3,000 a month, published this week:

```json
{
  "locations": ["Île-de-France"],
  "domains": ["M18"],
  "contractTypes": ["CDI"],
  "qualification": ["executive"],
  "salaryMin": 3000,
  "salaryPeriod": "monthly",
  "postedWithin": "7",
  "maxItems": 500
}
```

A search you already built on the website:

```json
{
  "searchUrls": ["https://candidat.francetravail.fr/offres/recherche?lieux=69123&typeContrat=CDI&emission=3&rayon=10&tri=1"],
  "maxItems": 300
}
```

### Output example

Here is a real record from a test run on 21 Oct 2026, with the description and lists shortened.

```json
{
  "jobId": "215LFRJ",
  "url": "https://candidat.francetravail.fr/offres/recherche/detail/215LFRJ",
  "title": "Chauffeur / Chauffeuse de poids lourd (H/F) (H/F)",
  "company": "TRANSSUD",
  "location": "31 - BRUGUIERES",
  "departmentCode": "31",
  "city": "BRUGUIERES",
  "latitude": 43.727074,
  "longitude": 1.412078,
  "contractType": "CDI",
  "workingTime": "Temps plein",
  "postedText": "Publié hier",
  "postedDaysAgo": 1,
  "postedDate": "2026-10-20",
  "badges": ["Employeur handi-engagé"],
  "disabilityCommittedEmployer": true,
  "source": "France Travail",
  "isPartnerOffer": false,
  "searchKeyword": "chauffeur poids lourd",
  "searchLocation": "Toulouse (31000, 31100, 31200, 31300, 31400, 31500)",
  "rank": 1,
  "description": "Nous recherchons un(e) Chauffeur / Chauffeuse de poids lourd afin de :\n\n- Préparer le chargement ...",
  "romeCode": "N4101",
  "romeLabel": "Chauffeur / Chauffeuse de poids lourd",
  "contractSummary": "CDI - Contrat travail",
  "schedule": ["35H/semaine", "Travail en journée"],
  "salaryText": "Mensuel de 2170.0 Euros à 2175.0 Euros",
  "salaryMin": 2170,
  "salaryMax": 2175,
  "salaryCurrency": "EUR",
  "salaryPeriod": "month",
  "qualification": "Ouvrier qualifié (P1,P2)",
  "experience": "Débutant accepté",
  "experienceRequirement": "beginner-accepted",
  "skills": [{ "name": "Contrôler l'état de fonctionnement du véhicule", "required": false }, "..."],
  "softSkills": ["Faire preuve de rigueur et de précision", "..."],
  "drivingLicences": [{ "name": "C - Poids lourd", "required": true }],
  "industry": "Transports routiers de fret de proximité",
  "companySize": "50 à 99 salariés",
  "nationalPrograms": ["Employeur Handi-engagé", "Plan \"1 jeune, 1 solution\""],
  "updatedDate": "2026-10-20"
}
```

Without `includeDetails`, each record stops at `rank` and then `scrapedAt`.

### Pricing

| What you run | Cost |
|---|---|
| 1,000 offers, search data | US$1.05 |
| 1,000 offers with full records | US$1.05 + US$0.40 = US$1.45 |
| 10,000 offers, search data | US$10.50 |

You pay only for offers saved to the dataset. Duplicates, such as one offer found by two keywords, are dropped before you're charged. `maxItems` is exact, and the run stops cleanly when it reaches your spending limit.

### Compared with the alternatives

- **The official France Travail API** (francetravail.io) is free but needs a registered application, OAuth credentials and your own code. This Actor needs none of that and returns a ready-made table.
- **Other France Travail Actors on the Store** charge between about US$0.79 and US$1.50 per 1,000 results. The most used one costs US$1.50. This Actor costs US$1.05 for search data and US$1.45 with full records. It also gives you coordinates, partner-board origin, badges, parsed salaries and every filter the website offers.
- **Limits:** like the website, each search returns at most 1,150 offers. Split large pulls by place, contract or domain. Results are de-duplicated across searches. Application links that sit behind France Travail's apply flow are not collected.

This Actor is built on our [Built In Jobs Scraper](https://apify.com/fabrikit/builtin-jobs-scraper) and uses the same pricing model, `maxItems` handling and privacy rules.

### Integrations

Schedule runs and send new offers to Google Sheets, Airtable, Slack or a webhook. You can also connect the Actor to n8n, Make or Zapier, or start runs and read datasets through the Apify API. AI agents can call it as a tool through the Apify MCP server, for example: "find CDI nursing jobs in Gironde published this week".

### FAQ

**Is it legal to scrape France Travail?** The Actor reads job offers that France Travail publishes openly, without logging in, and keeps no personal data. Check that your use fits France Travail's terms and the GDPR. This Actor is independent and not endorsed by France Travail.

**Do I need a proxy?** The default Apify proxy is expected to work. If France Travail starts refusing requests, the Actor switches to French RESIDENTIAL proxies on its own. The `SUMMARY` record shows which route was used.

**Why is `postedDate` a date without a time?** The website only says "Publié hier" or "il y a 5 jours". The Actor converts that label to a Paris calendar date. With details on, `updatedDate` gives the offer's last-modification date.

**What happens if a filter is not applied?** France Travail silently ignores parameters it does not know. The Actor compares what it sent with the query the site actually applied and lists any difference in `SUMMARY.ignoredFilters`.

### Changelog

- **0.1** (October 2026): first release. Keyword, ROME-code and place search with radius, every website filter, pasted search URLs, slices of up to 150 offers per request, exact `maxItems`, de-duplication, optional full offer records, automatic RESIDENTIAL fallback, contact redaction.

***

### En español

**France Travail Jobs Scraper** extrae ofertas de empleo de candidat.francetravail.fr, el servicio público de empleo de Francia (ex Pôle emploi), incluidas las de bolsas asociadas. Busca por palabra clave o código ROME y por ciudad, departamento, región o toda Francia, con los mismos filtros del sitio (contrato, fecha, dominio, experiencia, cualificación, salario). Con `includeDetails` añade la descripción completa, el salario con rango, competencias, idiomas, permisos y datos de la empresa. Precio: **US$1,05 por 1.000 ofertas** (+US$0,40 por 1.000 con detalle). No guarda datos de contacto de reclutadores.

# Actor input Schema

## `keywords` (type: `array`):

Job titles, skills or ROME occupation codes, one search per entry (for example: comptable, développeur, aide-soignant, N4101). Each keyword is combined with each place. Leave empty to list every offer in the places below.

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

Cities, departments, regions or France, one search per entry: "Lyon", "Toulouse", "Gironde", "33", "Bretagne", "France". Site place codes also work (75D, 53R, 31555). Leave empty to search all of France.

## `radiusKm` (type: `string`):

Distance around each city. Ignored for departments, regions and France.

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

Newest offers first, or France Travail's relevance order.

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

Only offers published in this period.

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

Only these contracts. Leave empty for all.

## `workingTime` (type: `array`):

Full-time, part-time and/or offers that do not say. Leave empty for all.

## `domains` (type: `array`):

Only offers in these France Travail domains. Leave empty for all.

## `experienceLevels` (type: `array`):

Only offers asking for this much experience. Leave empty for all.

## `qualification` (type: `array`):

Executive (cadre) and/or non-executive positions. Leave empty for all.

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

Only offers paying at least this gross amount in euros, per the period below (France Travail's own salary filter).

## `salaryPeriod` (type: `string`):

Period of the minimum salary above.

## `minContractMonths` (type: `integer`):

For fixed-term and temporary contracts: shortest duration in months.

## `maxContractMonths` (type: `integer`):

For fixed-term and temporary contracts: longest duration in months.

## `fewApplicantsOnly` (type: `boolean`):

France Travail's 'Soyez parmi les 1ers à postuler' filter: offers older than 15 days with fewer than 4 applications known to France Travail.

## `disabilityCommittedEmployersOnly` (type: `boolean`):

Only employers recognised as 'handi-engagé' by France Travail, Cap emploi and their partners.

## `adaptedCompaniesOnly` (type: `boolean`):

Only 'entreprises adaptées', companies employing mainly workers with disabilities.

## `includePartnerOffers` (type: `boolean`):

France Travail also lists offers from partner job boards (Meteojob, Beetween, Broadbean, Skello, Cookorico and others). Turn off to keep only offers posted directly with France Travail.

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

Optional: search URLs copied from candidat.francetravail.fr/offres/recherche with your filters already set. Each one is followed slice by slice.

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

Read each offer's full record: complete description, ROME code and occupation, salary text with parsed min/max/period, contract duration, schedule, benefits, qualification, experience, education, skills, soft skills, languages, driving licences, sector, company size and description, employer page and last update date. One extra request per offer, charged as the 'job-details' event. Off = fastest and cheapest.

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

Stop after this many unique offers across all searches (exact; duplicates are removed before counting). France Travail shows at most 1,150 offers per search: split big searches by place, contract or domain.

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

Apify Proxy settings. The Actor starts on the configured proxy (datacenter by default) and switches to Apify RESIDENTIAL (France) automatically if France Travail starts refusing requests.

## Actor input object example

```json
{
  "locations": [
    "Lyon"
  ],
  "radiusKm": "default",
  "sortBy": "date",
  "postedWithin": "any",
  "salaryPeriod": "monthly",
  "fewApplicantsOnly": false,
  "disabilityCommittedEmployersOnly": false,
  "adaptedCompaniesOnly": false,
  "includePartnerOffers": true,
  "includeDetails": false,
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

All job offers collected during the run

## `summary` (type: `string`):

Searches, pages, resolved places, filters the site did not apply, capped searches and network stats of the run

# 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 = {
    "locations": [
        "Lyon"
    ],
    "maxItems": 20,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("fabrikit/france-travail-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 = {
    "locations": ["Lyon"],
    "maxItems": 20,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("fabrikit/france-travail-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 '{
  "locations": [
    "Lyon"
  ],
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call fabrikit/france-travail-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,fabrikit/france-travail-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/KN5CjvDRYy2D2dugS/builds/qg0eynMKBVFQwsuve/openapi.json
