# France Travail Jobs Scraper ($0.50/1K) (`carabain-digital/francetravail-jobs`) Actor

Scrape job postings from France Travail (ex Pôle emploi, candidat.francetravail.fr): title, employer, city, contract (CDI, CDD, intérim, alternance), date and partner board; salary, ROME code and full text with the add-on. Filter by keyword, city, radius, contract.

- **URL**: https://apify.com/carabain-digital/francetravail-jobs.md
- **Developed by:** [Carabain Digital](https://apify.com/carabain-digital) (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 $0.30 / 1,000 job postings

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

#### What is France Travail Jobs Scraper?

**France Travail Jobs Scraper** scrapes **job postings (offres d'emploi) from France Travail ([candidat.francetravail.fr](https://candidat.francetravail.fr))**, the French public employment service (ex Pôle emploi) with roughly 750,000 current offers, including offers from partner boards such as HelloWork, Meteojob and Cadremploi. Search by **keyword, city, radius and publication date** and get clean, flat job data as JSON, CSV, Excel, XML or HTML: title, employer, city, contract type (CDI, CDD, alternance, stage), salary when published and a link to the job. Prefilled example: 20 `vendeur` jobs in Lyon, ready in seconds. Costs **$0.50 per 1,000 jobs**. Add-on: the full job text, salary, ROME occupation, experience, training and skills for $1.00 per 1,000.

- 🔎 **Search like on the site**: keyword, city, department or region + radius, contract type, posted in the last N days
- ⚡ **Fast and cheap**: no browser, no proxy needed, over 1,000 jobs in a few seconds
- 📚 **Full details on demand**: switch on **Full details** for the complete text, salary and ROME occupation
- 🧩 **One job schema for several countries**: same field names as our other job scrapers (FR, NL, BE, DE)
- 🔌 **Connect anywhere**: API, schedules, webhooks, Google Sheets, Make, Zapier, MCP / AI agents

#### What data can I extract from France Travail?

<table>
<tr><td>🆔 Stable job ID and URL</td><td>📝 Title and employer</td></tr>
<tr><td>📍 City, region</td><td>🌍 Latitude and longitude (with the add-on)</td></tr>
<tr><td>📅 Publication date</td><td>🕒 Contract type (CDI, CDD, alternance, stage...)</td></tr>
<tr><td>💶 Salary range and period (when published)</td><td>🏠 Remote / on-site / hybrid</td></tr>
<tr><td>🏢 Employer and origin (France Travail or partner board)</td><td>🧾 Short description</td></tr>
<tr><td>🧪 ROME occupation, experience, training (add-on)</td><td>⏱️ Working hours and contract duration (add-on)</td></tr>
</table>

Fields the site does not publish stay `null` (see the FAQ). Every item has the same keys, so exports line up.

#### How do I scrape France Travail jobs?

1. [Create a free Apify account](https://console.apify.com/sign-up) and open this Actor.
2. Enter a **Keyword** (for example `vendeur`) and optionally a **Location** and **Radius**.
3. Set **Max jobs**, and **Posted in the last N days** if you only want fresh jobs.
4. Optionally switch on **Full details** to include the full job text, salary, ROME occupation, experience, training and skills.
5. Click **Start**, then download the jobs from the **Output** tab as JSON, CSV, Excel, XML or HTML.

#### How much does it cost to scrape France Travail jobs?

You pay per job that ends up in your dataset: **$0.50 per 1,000 jobs**, no subscription. The monthly credit of Apify's Free plan ($5) covers around 10,000 jobs without add-ons. Paid plans get volume discounts.

- **Add-on: Full details, $1.00 per 1,000 jobs** (off by default). Adds the complete job description, the salary (parsed into min, max and period, and as the original text), the ROME occupation code, experience and training asked, skills, working hours, company website and last-modified date. One extra request per job. Charged only for jobs that were actually enriched.
- Failed runs and empty searches cost nothing; you can cap spending with **Maximum cost per run** in the run options.

See the **Pricing** tab for the current prices.

#### ⬇️ Input

| Field | Description |
|---|---|
| **Keyword** (`keyword`) | Job title or search term, French or English. Empty = all jobs |
| **Location** (`location`) | French city (`Lyon`), postcode (`69003`), department number (`69`) or region (`Occitanie`). Empty = all of France (then a keyword is required) |
| **Radius (km)** (`radius_km`) | Search radius around the location |
| **Posted in the last N days** (`posted_since_days`) | Only fresh jobs |
| **Contract types** (`ft_contract_types`) | CDI, CDD, intérim, saisonnier, apprentissage, professionnalisation |
| **Partner offers** (`ft_partner_offers`) | Include offers from partner boards (default yes) |
| **Max jobs** (`limit`) | Stop after this many jobs |
| **Full details** (`includeDetails`) | Paid add-on: the full job text, salary, ROME occupation, experience, training and skills |
| **Proxy** (`proxyConfiguration`) | Not needed for France Travail |

```json
{
    "keyword": "vendeur",
    "location": "Lyon",
    "radius_km": 25,
    "posted_since_days": 7,
    "limit": 20,
    "includeDetails": false
}
```

Enter a keyword, a location, or both: France Travail does not list all jobs without one of them. A city or postcode is turned into the official commune code, so `Lyon`, `69003` and `Paris 15` work; the radius is 0-100 km (the site's own default is 10 km).

France Travail shows at most **1,150 jobs per search**, newest first. For more, split the search by city, contract type or keyword.

#### ⬆️ Output

Jobs are stored in the default dataset, newest first. View them as a table in the **Output** tab or export JSON, CSV, Excel, XML or HTML.

##### Job from the search results

```json
{
    "id": "francetravail:215WDXY",
    "source": "francetravail",
    "url": "https://candidat.francetravail.fr/offres/recherche/detail/215WDXY",
    "title": "Boulanger-pâtissier / Boulangère-pâtissière (H/F)",
    "company": "LE 9EME PAIN",
    "company_url": null,
    "location": "LYON 09",
    "city": "LYON 09",
    "postcode": null,
    "region": null,
    "department": "69",
    "country": "FR",
    "lat": null,
    "lon": null,
    "remote": null,
    "posted_at": "2026-10-30",
    "valid_through": null,
    "employment_type": [
        "CDD",
        "Temps plein"
    ],
    "contract_type": "fixed_term",
    "contract_duration_months": null,
    "hours_per_week_min": null,
    "hours_per_week_max": null,
    "salary_min": null,
    "salary_max": null,
    "salary_currency": null,
    "salary_period": null,
    "salary_text": null,
    "education_level": null,
    "experience": null,
    "category": null,
    "rome_code": null,
    "sector": null,
    "skills": [],
    "origin": "France Travail",
    "description": "Le 9ème Pain, boulangerie à Lyon 9 recrute un(e) boulanger(e) - pâtissier(e) dans le cadre d'un remplacement congé maternité les horaires : 6h00 -14h00, du lundi au vendredi. CDD de 4 mois ...",
    "apply_url": null,
    "modified_at": null,
    "scraped_at": "2026-11-01T11:04:58Z"
}
```

##### The same kind of job with the Full details add-on

```json
{
    "id": "francetravail:215WDXY",
    "source": "francetravail",
    "url": "https://candidat.francetravail.fr/offres/recherche/detail/215WDXY",
    "title": "Boulanger-pâtissier / Boulangère-pâtissière (H/F)",
    "company": "LE 9EME PAIN",
    "company_url": null,
    "location": "LYON 09",
    "city": "LYON 09",
    "postcode": null,
    "region": null,
    "department": "69",
    "country": "FR",
    "lat": null,
    "lon": null,
    "remote": null,
    "posted_at": "2026-10-30",
    "valid_through": null,
    "employment_type": [
        "CDD",
        "Temps plein"
    ],
    "contract_type": "fixed_term",
    "contract_duration_months": 4,
    "hours_per_week_min": 35.0,
    "hours_per_week_max": 35.0,
    "salary_min": 2000.0,
    "salary_max": 2400.0,
    "salary_currency": "EUR",
    "salary_period": "month",
    "salary_text": "Mensuel de 2000.0 Euros à 2400.0 Euros",
    "education_level": "CAP, BEP et équivalents Spécialisation pâtisserie / CAP, BEP et équivalents - BOULANGERIE",
    "experience": "1 An(s)",
    "category": "Boulanger-pâtissier / Boulangère-pâtissière",
    "rome_code": "D1102",
    "sector": "Boulangerie et boulangerie-pâtisserie",
    "skills": [
        "Cuire des pièces de viennoiserie",
        "Caractéristiques des farines levure, additifs"
    ],
    "origin": "France Travail",
    "description": "Le 9ème Pain, boulangerie à Lyon 9 recrute un(e) boulanger(e) - pâtissier(e) dans le cadre d'un remplacement congé maternité les horaires : 6h00 -14h00, du lundi au vendredi. \nCDD de 4 mois  Démarrage en janvier. Le salaire sera en fonction de l'expérience.",
    "apply_url": null,
    "modified_at": "2026-10-30",
    "scraped_at": "2026-11-01T11:04:58Z"
}
```

#### What can I do with France Travail job data?

- 📈 **Labour market research**: track hiring demand per profession, contract type (CDI, alternance, stage) or region over time with scheduled runs
- 🎯 **Recruitment and lead generation**: find employers that are hiring in your field and who hires most
- 🔔 **Job alerts and aggregators**: feed fresh offres d'emploi into your own site, newsletter or Slack
- 🧠 **AI and analytics**: use job texts for skills extraction, salary models or LLM pipelines

#### Tips for best results

- Use **Contract types** (for example apprentissage for alternance) instead of putting those words in the keyword.
- Offers from partner boards (about 80% of the list) are marked in `origin`; switch off **Partner offers** to get only France Travail's own offers.
- Leave **Full details** off for monitoring and counting; switch it on when you need the text, the salary or the ROME occupation.
- Because one job can appear on France Travail and on a partner board, use the `title` + `company` + `city` to dedupe against other sources.
- For a daily feed, schedule a run with **Posted in the last N days** = 1 and a high **Max jobs**.
- Results from the same search are deduplicated by job ID.

#### Frequently asked questions

##### Can I use France Travail Jobs Scraper with the Apify API?

Yes. Every run has a dataset you can read through the [Apify API](https://docs.apify.com/api/v2). Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("carabain-digital/francetravail-jobs").call(run_input={
    "keyword": "vendeur",
    "location": "Lyon",
    "posted_since_days": 7,
    "limit": 100,
})
for job in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(job["posted_at"], job["title"], "-", job["company"])
```

JavaScript:

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('carabain-digital/francetravail-jobs').call({
    keyword: 'vendeur',
    location: 'Lyon',
    posted_since_days: 7,
    limit: 100,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.length, 'jobs');
```

##### Can I use France Travail Jobs Scraper through an MCP server or with AI agents?

Yes. Add it to an AI agent through the [Apify MCP server](https://mcp.apify.com) (`https://mcp.apify.com?tools=carabain-digital/francetravail-jobs`), or let the agent find it with `search-actors` and run it with `call-actor`. A small search (`limit` 20) finishes in seconds, and the dataset items are flat and small, so agents can read them with `get-dataset-items`. Example prompt: *"Use France Travail Jobs Scraper to find the 20 newest vendeur jobs in Lyon and summarise the employers and contract types."*

##### Can I integrate France Travail data with other apps?

Yes: Google Sheets, Slack, Make, Zapier, n8n, Airtable or your own webhook, through Apify [integrations](https://apify.com/integrations) and [webhooks](https://docs.apify.com/platform/integrations/webhooks). Schedule runs to keep the data fresh.

##### Why is a field empty?

The search results only carry title, employer, place, contract, working time, a 200-character snippet and the day of publication. Salary, ROME code, experience, training, skills, company website and the full text come with the **Full details** add-on, and only when the employer entered them (a salary for roughly 70% of the detailed jobs). France Travail does not publish coordinates, postcode, closing date or remote policy, so `lat`, `lon`, `postcode`, `valid_through` and `remote` are always null. Around 15% of offers are anonymous (`company` null).

##### Is the publication date exact?

It is the day, not the time. France Travail only shows "Publié aujourd'hui", "hier" or "il y a N jours" in the list, so `posted_at` is a date (Paris time). For offers older than 30 days the site shows "plus de 30 jours" and `posted_at` is that lower bound.

##### Why do I get at most 1,150 jobs?

France Travail itself caps every search at 1,150 results. Split the search per city, per contract type or per keyword to collect more.

##### Is it legal to scrape France Travail?

The Actor only collects publicly visible job postings, the same data anyone can see on candidat.francetravail.fr. Job postings can contain personal data (for example a contact person), and rules such as GDPR may apply to how you store and use it. Check your use case with a lawyer. More background: [Is web scraping legal?](https://blog.apify.com/is-web-scraping-legal/)

##### France Travail Jobs Scraper not working? Feedback

Open an issue on the **Issues** tab of this Actor with the run link and we will look at it. Feature ideas are welcome there too.

#### Other scrapers by us

| Actor | Covers |
|---|---|
| [France Jobs Scraper](https://apify.com/carabain-digital/france-jobs) | Welcome to the Jungle and France Travail in one run, merged and deduplicated |
| [Welcome to the Jungle Jobs Scraper](https://apify.com/carabain-digital/welcometothejungle-jobs) | France: welcometothejungle.com, employer-brand job board |
| [Arbeitsagentur Jobs Scraper](https://apify.com/carabain-digital/arbeitsagentur-jobs) | Germany: Bundesagentur für Arbeit Jobbörse |
| [StepStone Jobs Scraper](https://apify.com/carabain-digital/stepstone-jobs) | Germany: stepstone.de |
| [VDAB Jobs Scraper](https://apify.com/carabain-digital/vdab-jobs) | Belgium (Flanders): VDAB |
| [Jobbird Jobs Scraper](https://apify.com/carabain-digital/jobbird-jobs) | Netherlands, Belgium, Germany: Jobbird job aggregator |

⭐ **Does it work well for you?** A review on the Store page helps others find this Actor and helps us keep it maintained.

# Actor input Schema

## `keyword` (type: `string`):

Job title or search term, French. Example: `vendeur`, `infirmier`, `développeur web`. Several words narrow the search. Needs a keyword or a location.

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

French city, postcode, department number or region. Example: `Lyon`, `69003`, `69` or `Occitanie`. Leave empty for all of France (then a keyword is required).

## `radius_km` (type: `integer`):

Search radius around the city in kilometres, 0 to 100. Example: `25`. Needs a location. France Travail's own default is 10 km.

## `posted_since_days` (type: `integer`):

Only jobs published in the last N days. Example: `7`. The site filters in steps of 1, 3, 7, 14 and 31 days; we then cut to the exact number of days. Leave empty for all.

## `ft_contract_types` (type: `array`):

Only these contract types. Example: `Apprentissage` for alternance. Leave empty for all types.

## `ft_partner_offers` (type: `boolean`):

Also return offers that France Travail republishes from partner job boards (HelloWork, Meteojob, Cadremploi, ...). They make up most of the list. Switch off to get only France Travail's own offers.

## `limit` (type: `integer`):

Stop after this many jobs (newest first). Example: `100`. France Travail shows at most 1,150 jobs per search.

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

Also fetch each job's detail: the full job description, salary (min, max, period and original text), ROME occupation code, experience and training asked, skills, working hours, company website and last-modified date. Adds $1.00 per 1,000 jobs on top of the base price. One extra request per job.

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

France Travail works without a proxy. Enable one only if runs get blocked.

## Actor input object example

```json
{
  "keyword": "vendeur",
  "location": "Lyon",
  "ft_partner_offers": true,
  "limit": 20,
  "includeDetails": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

All scraped jobs, one item per job posting.

# 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 = {
    "keyword": "vendeur",
    "location": "Lyon",
    "limit": 20,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("carabain-digital/francetravail-jobs").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 = {
    "keyword": "vendeur",
    "location": "Lyon",
    "limit": 20,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("carabain-digital/francetravail-jobs").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 '{
  "keyword": "vendeur",
  "location": "Lyon",
  "limit": 20,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call carabain-digital/francetravail-jobs --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,carabain-digital/francetravail-jobs"
        }
    }
}
```

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/7hpUfWzUNtIwOsNbj/builds/BI8OjjvhGuCjjnPnv/openapi.json
