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

The HelloWork Jobs Scraper extracts French job listings from HelloWork.com by keyword and location, capturing titles, companies, contracts, exact vs approximate search matches, recruiter vs estimated salaries, advertiser types and full descriptions — ideal for recruiting and salary benchmarking.

- **URL**: https://apify.com/piotrv1001/hellowork-jobs-scraper.md
- **Developed by:** [FalconScrape](https://apify.com/piotrv1001) (community)
- **Categories:** Jobs
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 1,000 job listings

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

### 🚀 HelloWork Jobs Scraper

Extract French job listings from HelloWork (formerly RegionsJob) by keyword, town, postcode, department or region. The **HelloWork Jobs Scraper** returns clean job records with salaries, contracts, remote-work tags, advertiser types and full descriptions. It suits regional recruitment research, salary benchmarking and job-market monitoring in France.

Unlike a plain export, every job says **how well it matches your search**, and every salary says **where it comes from**. You can keep exact matches apart from HelloWork's "similar jobs nearby" padding, and keep recruiter-provided salaries apart from HelloWork estimates.

### ✨ Features

- 🎯 **Exact vs approximate matches**: HelloWork pads searches with similar titles and nearby places. Each job carries the site's own `searchMatch` label (`exact` or `approximate`). Turn on **Exact matches only** to drop the padding. Dropped jobs are never charged. Example: the default search `développeur` in Saint-Malo returns 46 jobs, of which only 6 are exact matches.
- 💶 **Salary with its source**: `salarySource` is `recruiter` (published by the advertiser), `estimate` (HelloWork's own estimate) or `none`. Recruiter and estimated amounts go into separate fields, so an estimate is never presented as an employer offer. Hourly, monthly and yearly amounts are kept in their original period, never annualised.
- 🏢 **Advertiser type**: shows when a job is posted by an **ESN** (IT services firm), a **Cabinet de recrutement** (recruitment agency) or an **Agence d'intérim** (temp agency) rather than directly by the employer. You also get the advertiser's HelloWork profile URL and logo.
- 📍 **Precise location control**: search a town, postcode, department or region with a 0, 5, 10, 20 or 50 km radius. The run summary shows the place and radius HelloWork actually used. Unknown places are rejected instead of silently searching all of France.
- 🔎 **Filters**: contract type (CDI, CDD, Intérim, Stage, Alternance, Freelance…) and posting date (24 hours, 3 days, a week, a month).
- 🔗 **URLs welcome**: paste HelloWork search pages copied from your browser (with any filters applied on the site), job list pages or single job pages.
- 📄 **Full job details** (optional): full description and candidate profile, postcode, region, education level, experience, contract duration, skills, industry, job category, and exact posting and expiry dates.

### 🛠️ How It Works

1. **Enter a keyword and a location**, for example `comptable` in `Nantes`, or paste HelloWork URLs.
2. **Pick the radius and filters**, and turn on **Exact matches only** if you want only the site's exact matches.
3. **Turn on Scrape full job details** if you need salaries, descriptions and advertiser types.
4. **Run the scraper** and download the results as JSON, CSV or Excel, or connect them to your tools through the API.

Every run also saves a `RUN_SUMMARY` record. Per search, it lists the resolved locality, the radius used, HelloWork's total job count, the number of exact and approximate matches, and why the search stopped.

### 💰 Pricing

Pay only for the jobs you get:

| Event       | Price           | What you get                                                                                                                                                 |
| ----------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Job listing | $0.0008 per job | Title, company, location, contract, remote-work tag, posting age, search-match label and URL                                                                 |
| Job detail  | $0.0015 per job | Everything above, plus salary with its source, advertiser type, full description, candidate profile, postcode, education, experience, skills and exact dates |

A job detail is charged **instead of** a job listing, not on top of it. 1,000 jobs from search results cost $0.80, and 1,000 jobs with full details cost $1.50. Approximate matches dropped by **Exact matches only** are free.

### 📊 Sample Output Data

A job with full details:

```json
{
    "jobId": "82144365",
    "url": "https://www.hellowork.com/fr-fr/emplois/82144365.html",
    "title": "CDI Développeur 4D H/F",
    "companyName": "Kersia",
    "location": "Dinard - 35",
    "contractType": "CDI",
    "remoteWork": null,
    "superRecruiter": false,
    "postedAgo": "il y a 16 jours",
    "searchMatch": "exact",
    "searchKeywords": "développeur",
    "searchLocation": "Saint-Malo",
    "searchUrl": "https://www.hellowork.com/fr-fr/emploi/recherche.html?k=d%C3%A9veloppeur&l=Saint-Malo&ray=20",
    "companyProfileUrl": "https://www.hellowork.com/fr-fr/entreprises/kersia-7613.html",
    "companyLogoUrl": "https://f.hellowork.com/img/entreprises/160_160/198389.png",
    "advertiserType": null,
    "city": "Dinard",
    "postalCode": "35800",
    "region": "Bretagne",
    "country": "FR",
    "jobLocationType": null,
    "employmentType": ["FULL_TIME"],
    "contractDuration": null,
    "salarySource": "estimate",
    "salaryText": "Estimation Hellowork → 28 000 - 44 000 € / an",
    "recruiterSalaryMin": null,
    "recruiterSalaryMax": null,
    "estimatedSalaryMin": 28000,
    "estimatedSalaryMax": 44000,
    "salaryPeriod": "YEAR",
    "salaryCurrency": "EUR",
    "experience": "Exp. 0 - 2 ans (débutants acceptés)",
    "education": "Bac +2",
    "industry": "Agriculture • Pêche",
    "occupationalCategory": "Informatique",
    "skills": ["SOAP", "API", "REST", "4e Dimension"],
    "datePosted": "2026-09-07T00:09:08Z",
    "validThrough": "2026-10-07T00:09:08Z",
    "directApply": false,
    "description": "Les missions du poste\nRejoindre Kersia, c'est s'engager à contribuer à une grande ambition…",
    "descriptionHtml": "<h2>Les missions du poste</h2><p>Rejoindre Kersia…</p>",
    "profile": "Vous êtes titulaire d'un Bac +2 minimum en informatique…",
    "detailStatus": "ok",
    "scrapedAt": "2026-09-23T09:08:17.867Z"
}
```

A search-result listing (full details off) contains the fields from `jobId` to `searchUrl` plus `scrapedAt`.

### ❓ FAQ

**What does `searchMatch` mean?** It is HelloWork's own label for each result of your search. `exact` jobs match the keyword and place. `approximate` jobs are similar titles or nearby places that HelloWork adds to fill the list. It is the site's classification, so an exact label does not guarantee the job suits your needs. Job list pages (such as "développeur informatique in Lyon") carry the page's own label instead.

**Is `recruiterSalaryMin` the real salary?** It is the salary the advertiser published. Nobody verifies it independently. HelloWork estimates go into `estimatedSalaryMin`/`estimatedSalaryMax` and are never mixed in.

**Who is the employer when `advertiserType` is "Cabinet de recrutement"?** The job is posted by a recruitment agency on behalf of a client. `companyName` is the agency, and the client is usually not named. An empty `advertiserType` does not prove the job is posted directly by the employer.

**What does a radius of 0 km do?** It keeps jobs in the town itself, without the surrounding area. HelloWork's default radius is 20 km.

Start collecting French job and salary data with the **HelloWork Jobs Scraper** today! 🚀

# Actor input Schema

## `keywords` (type: `string`):

What to search for, e.g. `développeur`, `comptable`, `infirmier`, `commercial`. Leave empty to get every job in the location.

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

A French town, postcode, department or region, e.g. `Nantes`, `35000`, `Bretagne`. Unknown places are rejected instead of silently searching all of France. Leave empty to search nationwide.

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

How far around the location to search. `0 km` keeps only the town itself. HelloWork's own default is 20 km.

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

Only jobs with one of these contracts. Leave empty for all.

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

Only jobs posted recently.

## `exactMatchesOnly` (type: `boolean`):

HelloWork pads searches with approximate matches (similar titles, nearby places). Every job carries the site's own `searchMatch` label (`exact` or `approximate`); turn this on to drop the approximate ones. Dropped jobs are not charged and are counted in the run summary.

## `startUrls` (type: `array`):

Search pages copied from your browser (with any filters applied on the site), job list pages such as `https://www.hellowork.com/fr-fr/emploi/metier_developpeur-informatique-ville_lyon-69000.html`, or single job pages like `https://www.hellowork.com/fr-fr/emplois/83605035.html`. The radius, contract and date inputs above apply only to the keyword search.

## `scrapeDetails` (type: `boolean`):

Open every job and add the salary with its source (recruiter-provided vs HelloWork estimate, never mixed), the advertiser type (ESN, recruitment agency, temp agency), full description and candidate profile, postcode and region, education, experience, skills, industry and exact posting and expiry dates. Charged as a job detail instead of a job listing. Job page URLs always include full details.

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

Maximum number of jobs to save.

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

Proxy used to reach hellowork.com. The default works for most runs.

## Actor input object example

```json
{
  "keywords": "développeur",
  "location": "Saint-Malo",
  "radiusKm": "20",
  "postedWithin": "all",
  "exactMatchesOnly": false,
  "scrapeDetails": false,
  "maxItems": 50,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `summary` (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 = {
    "keywords": "développeur",
    "location": "Saint-Malo",
    "maxItems": 50,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("piotrv1001/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": "développeur",
    "location": "Saint-Malo",
    "maxItems": 50,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("piotrv1001/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": "développeur",
  "location": "Saint-Malo",
  "maxItems": 50,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call piotrv1001/hellowork-jobs-scraper --silent --output-dataset

```

## MCP server setup

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