# HelloWork Jobs Scraper (`deriverge/hellowork-jobs-scraper`) Actor

French job ads from hellowork.com with the contract type (CDI, CDD, intérim), the salary or HelloWork's own estimate, the department and the full text. Search by keyword and place, filter by contract, experience or date, or paste a HelloWork search link.

- **URL**: https://apify.com/deriverge/hellowork-jobs-scraper.md
- **Developed by:** [deriverge s.r.o.](https://apify.com/deriverge) (community)
- **Categories:** Jobs, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.25 / 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.
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

## HelloWork Jobs Scraper

HelloWork Jobs Scraper exports job ads from hellowork.com, a French job board, one row per ad: title, employer, city with postcode, department and region, contract type (CDI, CDD, Intérim, Alternance and others), salary as numbers or HelloWork's own estimate, remote work, education, skills and the full text. The form comes filled in with `comptable`: click **Start** for 20 ads, then change the keyword. About one ad in seven shows neither a salary nor an estimate. It costs $0.50 per 1,000 jobs on the Free plan ($0.25 on Business), and the $5 of monthly credit in Apify's Free plan covers about 10,000 jobs.

### What data does it return?

| Field | Description |
|---|---|
| `title` | Job title as the employer wrote it, usually ending in `H/F` (for men and women): `Collaborateur Comptable H/F`. |
| `company`, `companyUrl` | Employer or recruitment firm, and its page on HelloWork. |
| `location`, `city`, `postcode` | Place as HelloWork lists it (`Metz - 57`), the city and the five-digit postcode. |
| `department`, `region` | French department number, such as `14` or `75`, and the region, such as `Normandie`. |
| `contractType` | Contract as HelloWork labels it: `CDI`, `CDD`, `Intérim`, `Stage`, `Alternance`, `Indépendant` or `Freelance`. |
| `employmentType` | Hours and contract flags from the job page, such as `FULL_TIME`, `PART_TIME` or `TEMPORARY`. |
| `remote`, `remoteLevel` | `remoteLevel` is the télétravail tag on the job page: `full` (Télétravail complet), `partial` (Télétravail partiel) or `occasional` (Télétravail occasionnel). `remote` is `true` with any of them, or when the page's structured data marks the job as remote. Both stay empty when the page says neither. |
| `salaryMin`, `salaryMax`, `salaryPeriod` | Published pay in euros as numbers, with `yearly`, `monthly`, `hourly` or `daily`. |
| `estimatedSalaryMedian`, `estimatedSalaryLow`, `estimatedSalaryHigh` | HelloWork's own yearly estimate for ads without a published salary: the median and the 10th and 90th percentiles. |
| `experienceText`, `experienceYearsMin`, `experienceYearsMax` | The experience tag on the job page as shown, such as `Exp. 3 à 5 ans` on the example ad, and its years as numbers, `3` and `5`. `Exp. 2 ans min.` gives `2` and no upper bound; `Débutant accepté` gives `0` and no upper bound. |
| `experienceMonths` | Required experience in months, from HelloWork's structured data. It is coarse; see Limits. |
| `education` | Education level, e.g. `associate degree` where the ad says Bac +2. |
| `category`, `industries` | HelloWork's job category, such as `Comptabilité` or `Informatique`, and the employer's sector, such as `Services aux Entreprises`. |
| `skills`, `qualifications` | Skill tags on the ad, and its candidate profile section as text. |
| `superRecruiter`, `easyApply` | `true` when HelloWork marks the recruiter as a responsive Super recruteur, and when you can apply on HelloWork directly. |
| `postedAt`, `expiresAt` | When the ad was published and when it closes, in ISO 8601; every ad read in September 2026 closed 30 days after publication. `postedText` keeps the age as shown, e.g. `il y a 3 jours`. |
| `description`, `descriptionHtml` | The full ad as plain text and as HTML. |
| `detailsIncluded` | `false` when the job page could not be read, so only the search result fields are filled. |
| `searchQuery`, `scrapedAt` | The search that found the ad, and when the ad was read. |

### How to scrape HelloWork jobs

1. Enter **Keywords** the way you would type them into HelloWork's search box, one per line: a job title, a skill or an employer (`comptable`, `infirmier`, `développeur`). Each keyword is a separate search, and an ad that two searches find comes back once.
2. Add **Locations** as cities (`Nantes`), department numbers (`33`) or regions (`Occitanie`). Every keyword is searched in every location. Leave the field empty for the whole of France.
3. Choose the filters HelloWork applies on its side: **Contract types**, **Remote work** (full, partial, occasional or none), **Experience**, **Advertiser type** (companies, recruitment firms, IT services firms, temp agencies, training centres), **Hours**, **Posted within** and **Sort by**.
4. For a filter the form does not offer, run the search on hellowork.com and paste its address into **Search links from hellowork.com (optional)**.
5. Keep **Include full details** on for the salary, postcode, region, remote level, experience, education, skills and full text. Turned off, the run returns the search result fields only, at the same price.
6. Click **Start**. With full details on, ads reach the **Output** tab at about 300 a minute, and you can export them as CSV, Excel or JSON.

In API input the filters take HelloWork's own codes, listed in the input schema: `Travail_temp` is interim, `Complet` full remote and `2-3y` two to three years of experience. For example:

```json
{
  "keywords": ["comptable", "contrôleur de gestion"],
  "locations": ["Lyon", "33"],
  "contractTypes": ["CDI"],
  "remote": ["Complet", "Partiel"],
  "postedWithin": "week",
  "maxItems": 500
}
```

### Example output

One ad from a run on 30 September 2026, with `description`, `descriptionHtml` and `qualifications` shortened.

```json
{
  "key": "hellowork:82668979",
  "jobId": "82668979",
  "title": "Comptable Generale - Comptable General H/F",
  "url": "https://www.hellowork.com/fr-fr/emplois/82668979.html",
  "company": "Batigère",
  "companyUrl": "https://www.hellowork.com/fr-fr/entreprises/batigere-155242.html",
  "companyLogo": "https://f.hellowork.com/img/entreprises/160_160/215007.png",
  "location": "Metz - 57",
  "city": "Metz",
  "postcode": "57000",
  "department": "57",
  "region": "Grand Est",
  "country": "FR",
  "contractType": "CDI",
  "employmentType": [
    "FULL_TIME"
  ],
  "remote": true,
  "remoteLevel": "partial",
  "salaryMin": 25200,
  "salaryMax": 30000,
  "salaryPeriod": "yearly",
  "salaryCurrency": "EUR",
  "estimatedSalaryMedian": null,
  "estimatedSalaryLow": null,
  "estimatedSalaryHigh": null,
  "experienceMonths": 12,
  "experienceText": "Exp. 2 ans min.",
  "experienceYearsMin": 2,
  "experienceYearsMax": null,
  "education": [
    "bachelor degree",
    "associate degree"
  ],
  "category": "Comptabilité",
  "industries": [
    "Immobilier"
  ],
  "skills": [
    "Rapprochement bancaire",
    "Excel",
    "Suivi des sinistres",
    "Sens du relationnel",
    "Logiciels bureautiques",
    "Comptabilité générale",
    "Principes comptables",
    "Capacité d’adaptation",
    "Esprit d'analyse"
  ],
  "superRecruiter": false,
  "easyApply": false,
  "postedText": "il y a 5 jours",
  "postedAt": "2026-09-25T00:16:36Z",
  "expiresAt": "2026-10-25T00:16:36Z",
  "qualifications": "Formation & Expérience\n\n- Titulaire d'un Bac +2/+3 en comptabilité, finance ou équivalent\n\n- Vous justifier d'une première expérience de minimum 3 ans sur un poste ...",
  "description": "Les missions du poste\nVous placez l'humain au coeur de vos valeurs et souhaitez vous impliquer au sein d'une entreprise responsable et engagée, notre vocation sociale et la diversité de nos métiers répondront à vos attentes. Spécialisées dans le logement social, l'accession sociale et l'accompagnement des publics fragiles, les ...",
  "descriptionHtml": "<h2>Les missions du poste</h2><p>Vous placez l'humain au coeur de vos valeurs et souhaitez vous impliquer au sein d'une entreprise responsable et engagée, notre vocation sociale et la diversité de nos métiers répondront à vos attentes. ...",
  "detailsIncluded": true,
  "searchQuery": "\"comptable\"",
  "scrapedAt": "2026-09-30T10:18:43.528Z"
}
```

### How much does it cost to scrape HelloWork?

| | Free plan | Starter | Scale | Business |
|---|---|---|---|---|
| 1,000 jobs | $0.50 | $0.40 | $0.325 | $0.25 |

You pay only for the events in the table. There is no start fee, and compute time and proxies are included.

Exporting 10,000 jobs with full details costs $5.00 on the Free plan and $2.50 on Business. A job found by two searches is charged once, and jobs dropped by **Exclude keywords** or already sent in new-only mode are not charged.

### Limits

- HelloWork covers France, including the overseas departments (region `Outre Mer`). A search is read to its last page, 30 ads at a time; `commercial` alone matched about 81,000 ads in September 2026.
- `experienceMonths` comes from HelloWork's structured data, which rounds experience into broad bands: of 1,038 ads in a September 2026 run, 441 had no value and all the others `12` or `84`. The example ad asks for 3 to 5 years and shows `12`.
- A tag with a single figure and no "min.", such as `Exp. 3 ans`, puts that figure in both `experienceYearsMin` and `experienceYearsMax`. Ads without the tag leave the three experience fields empty; `qualifications` often states the requirement in words.
- HelloWork puts no télétravail tag on ads without home office, so `remote` does not come back `false` for them. To get only such ads, choose No remote work in **Remote work**.
- About 3% of ad pages could not be opened in September 2026. Those rows have `detailsIncluded: false`, only the search result fields and a `postedAt` date worked out from `postedText`.
- `region` is what the ad states, and a few ads still name regions merged in 2016, such as `Languedoc-Roussillon`.
- If HelloWork answers with HTTP 403, 429 or a verification page, the run stops and keeps the ads it already has.
- A run returns at most 1,000 jobs unless you raise **Maximum jobs** (the form starts at 20). When the limit is lower than the results, each search gets an equal share.

### Salaries and HelloWork's estimate

Employers on HelloWork publish pay per year, month, hour or day, and `salaryPeriod` says which: `2500` to `2800` is a monthly salary, `30000` to `40000` a yearly one. When an ad has no salary, HelloWork adds its own estimate for the job, returned as a yearly median with the 10th and 90th percentiles as the low and high end. In runs of about 1,000 ads in September 2026, 60% had a published salary and 25% only the estimate. No ad had both.

### FAQ

#### Is it legal to scrape HelloWork?

HelloWork shows these ads to every visitor without an account. The actor reads the ad and the employer and nothing about the people who post or answer it. Ad texts belong to the employers, so check HelloWork's terms before you republish them; how you use the data is your responsibility.

#### What do CDI, CDD and the other contract types mean?

They are French contract types. A CDI (contrat à durée indéterminée) is a permanent contract and a CDD (contrat à durée déterminée) a fixed-term one. Intérim is temporary work through an agency, Stage an internship, Alternance a work-study contract that combines a job with school, and Indépendant self-employed work. **Contract types** filters on these labels in the search itself.

#### Can I search in English?

HelloWork matches English terms too, but the ads are written in French and French terms find more: on 30 September 2026 `accountant` matched 28,368 ads and `comptable` 33,808.

#### How do I get only new ads each day?

Turn on **Return only jobs new since the last run**, set a **Watch name** such as `comptable-lyon` (a saved task gets one automatically) and schedule the run daily. An ad you have received is skipped for 120 days and not charged again.

### Related scrapers

- [Welcome to the Jungle Jobs Scraper](https://apify.com/deriverge/welcome-to-the-jungle-jobs-scraper)
- [French Company Registry Scraper](https://apify.com/deriverge/french-company-check)
- [jobs.ch Scraper](https://apify.com/deriverge/jobs-ch-scraper)
- [Arbeitsagentur Jobs Scraper](https://apify.com/deriverge/arbeitsagentur-jobs-scraper)
- [Career Site Jobs Search](https://apify.com/deriverge/career-site-jobs-search)

### Support

This actor is built and maintained by deriverge s.r.o., a software company based in the Czech Republic. If a run fails or a field you need is missing, please open an issue in the **Issues** tab or write to us at info@deriverge.com. We respond in English and Czech. Runs can be scheduled in Apify Console or started from the **API** tab, which has examples for Python, JavaScript and cURL and works with Make, Zapier, n8n and the Apify MCP server. If the actor saves you time, a short review helps other people find it.

# Changelog

This Actor's version history is a separate document: https://apify.com/deriverge/hellowork-jobs-scraper/changelog.md

# Actor input Schema

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

What to search for, as in the HelloWork search box, usually in French: a job title, skill or company, for example "développeur", "infirmier" or "commercial". Each keyword is its own search. Leave empty for all jobs.

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

French cities, departments or regions, for example Paris, Lyon, Bordeaux, 33 or Occitanie. Each location is its own search. Leave empty for all of France.

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

Only jobs with these contract types. Leave empty for all.

## `remote` (type: `array`):

Only jobs with these remote work options (télétravail). Leave empty for all.

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

Only jobs posted within this period.

## `experience` (type: `array`):

Only jobs asking for this experience. Leave empty for all.

## `employerTypes` (type: `array`):

Only jobs from these kinds of advertisers. Leave empty for all.

## `hours` (type: `string`):

Full-time or part-time jobs.

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

Order of the results, as on HelloWork.

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

HelloWork search addresses with your filters, for example https://www.hellowork.com/fr-fr/emploi/recherche.html?k=infirmier\&l=Nantes. Each link is its own search.

## `excludeKeywords` (type: `array`):

Drop jobs whose title or company contains any of these.

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

Opens each job for the salary, HelloWork salary estimate, postcode, region, remote work, experience, education, skills, category, expiry date and the full description. The price is the same.

## `newOnly` (type: `boolean`):

Keeps a snapshot per watch name (or per saved task) and returns only jobs that were not there before. Schedule it daily for a job alert.

## `watchName` (type: `string`):

Name of the snapshot used by the new-only mode, for example "comptable-lyon". Runs from a saved task get one automatically.

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

Hard cap on returned jobs. When the cap is smaller than the results, every search gets an equal share.

## Actor input object example

```json
{
  "keywords": [
    "comptable"
  ],
  "postedWithin": "any",
  "hours": "any",
  "sortBy": "relevance",
  "includeDetails": true,
  "newOnly": false,
  "maxItems": 20
}
```

# Actor output Schema

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

One row per job with company, location, contract, salary, remote work, experience, skills and full description.

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

Jobs matching and returned per search, details read, dropped rows and warnings.

# 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 = {
    "keywords": [
        "comptable"
    ],
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("deriverge/hellowork-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 = {
    "keywords": ["comptable"],
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("deriverge/hellowork-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 '{
  "keywords": [
    "comptable"
  ],
  "maxItems": 20
}' |
apify call deriverge/hellowork-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,deriverge/hellowork-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/A1LVi5PN6BnLHEKvY/builds/LgMshVSurIKgH3DV6/openapi.json
