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

Scrape live job listings from HelloWork.com, one of France's largest job boards. Search by keyword, browse by region/city or by sector, and filter by contract type, work time, salary, and posted date.

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

## Pricing

from $3.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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

## HelloWork Jobs Scraper

Scrape **HelloWork.com** — one of France's largest job boards — for live job listings. Search by keyword, browse by region or city, or browse by sector/job function, with filters for contract type, remote-work frequency, employment schedule, experience level, company type, CSR label, posted-within window, disclosed salary, and search radius. HTTP-only via the public hellowork.com search pages. No auth, no proxy, no cookies required.

### What this actor does

- **Three modes:** `search` (keyword), `byLocation` (region/city browse), `bySector` (sector/job-function browse)
- **18 French regions** (including Guadeloupe, Martinique, Guyane, La Réunion, Mayotte), **26 industry sectors**, **34 job functions**, **6 experience-level bands**, **5 company types**, and **10 CSR/sustainability labels** as ready-to-use dropdowns
- **Filters:** contract type (CDI/CDD/Intérim/Stage/Alternance and more), remote-work (télétravail) frequency, employment schedule (full-time/part-time), experience level, company type, CSR label, posted-within window, minimum disclosed salary, search radius (mode=byLocation with `city`), disclosed-salary-only, super-recruiter-only — combinable across all modes
- **Structured salary parsing:** raw display text plus derived min/max/period/currency when the employer discloses a salary range
- **Empty fields are omitted**

### Output per job

- `offerId` — HelloWork internal offer ID
- `title` — job title
- `company` — hiring company name
- `companyLogoUrl` — company logo image URL
- `location` — free-text location (e.g. `Limonest - 69`)
- `department` — French department code, when derivable from `location` (e.g. `69`, `2A`)
- `contractType` — e.g. `CDI`, `CDD`, `Intérim`, `Stage`, `Alternance`
- `workTime` — employment schedule: `Temps Plein` (full-time) / `Temps Partiel` (part-time) / `Temps Occasionnel` (occasional), when disclosed
- `remoteWork` — remote-work (télétravail) frequency: `Télétravail Complet` (fully remote) / `Télétravail Partiel` (hybrid) / `Télétravail Occasionnel` (occasional remote), when disclosed on the listing card
- `salary` — raw disclosed salary text (e.g. `50 000 - 55 000 € / an`), when disclosed
- `salaryMin`, `salaryMax`, `salaryPeriod`, `salaryCurrency` — parsed salary amounts, when parseable
- `postedDate` — approximate UTC timestamp derived from HelloWork's relative posting text
- `postedDateRelative` — HelloWork's own relative posting text (e.g. `il y a 3 jours`)
- `hasApplicationTracking` — true when the recruiter shares application-progress tracking with candidates
- `isSuperRecruiter` — true for HelloWork-verified "super recruiter" employers
- `url` — canonical hellowork.com job detail page
- `recordType: "job"`, `scrapedAt`

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `search` | `search` / `byLocation` / `bySector` |
| `searchQuery` | string | – | Free-text keyword (mode=search); combinable with all filters below |
| `region` | string | – | French administrative region (mode=byLocation, unless `city` is set) |
| `city` | string | – | French city/commune name (mode=byLocation, unless `region` is set); takes priority over `region` |
| `sector` | string | – | Industry sector (mode=bySector, unless `jobFunction` is set) |
| `jobFunction` | string | – | Job function / métier (mode=bySector, unless `sector` is set) |
| `contractTypes` | array | – | One or more contract types |
| `remoteWork` | array | – | Remote-work (télétravail) frequency: fully / hybrid / occasional / none disclosed |
| `employmentType` | array | – | Employment schedule: full-time / part-time / unspecified |
| `experienceLevels` | array | – | Years of experience the employer asks for |
| `companyTypes` | array | – | Direct employer / recruitment agency / IT services company / temp agency / training center |
| `csrLabels` | array | – | CSR / sustainability certification held by the employer |
| `minSalary` | int | `0` | Minimum disclosed annual salary floor in EUR (0–100,000, matches HelloWork's own slider) |
| `radiusKm` | int | `20` | Search radius around `city` in km (0/5/10/20/50); ignored when only `region` is set |
| `postedWithin` | string | `all` | Any time / last 24h / last 3 days / last week / last month |
| `sortBy` | string | `relevance` | `relevance` or `date` (newest first) |
| `salaryOnly` | boolean | `false` | Only offers that disclose a salary range |
| `superRecruiterOnly` | boolean | `false` | Only HelloWork-verified "super recruiter" employers |
| `maxItems` | int | `50` | Hard cap on emitted job listings (1–1000) |

#### Example: keyword search

```json
{
  "mode": "search",
  "searchQuery": "developpeur",
  "sortBy": "date",
  "maxItems": 50
}
```

#### Example: browse by region + contract type, full-time only

```json
{
  "mode": "byLocation",
  "region": "Bretagne",
  "contractTypes": ["CDI"],
  "employmentType": ["ft"],
  "postedWithin": "w",
  "maxItems": 100
}
```

#### Example: browse by sector across France, salary disclosed only

```json
{
  "mode": "bySector",
  "sector": "Inform_SSII",
  "jobFunction": "Informatique_dev",
  "salaryOnly": true,
  "sortBy": "date",
  "maxItems": 100
}
```

#### Example: browse by city with multiple contract types and a 10km radius

```json
{
  "mode": "byLocation",
  "city": "Lyon",
  "radiusKm": 10,
  "contractTypes": ["CDI", "CDD", "Alternance"],
  "maxItems": 60
}
```

### Use cases

- **Recruitment agencies** — monitor new listings in a target French region or sector
- **Labor market research** — track job posting volume and salary disclosure by sector over time
- **HR tech / job aggregators** — feed structured French job data into your own platform
- **Salary & demand analysis** — combine sector/function filters with disclosed-salary data to study hiring trends
- **Relocation & recruiting platforms** — surface opportunities in a specific French region or city
- **Remote-work / ESG sourcing** — combine `remoteWork` and `csrLabels` to find fully-remote roles at certified socially-responsible employers

### FAQ

**What is HelloWork?** One of France's largest job boards, aggregating listings from thousands of French employers and recruitment agencies. See [hellowork.com](https://www.hellowork.com).

**Is this affiliated with HelloWork?** No — this is an independent third-party actor that reads HelloWork's public search-results pages. No login, cookies, or paid API is required.

**Can I combine keyword search with a location or sector filter?** Yes — `region`/`city` and `sector`/`jobFunction` work as additional filters on `search` mode too, not just their own dedicated modes.

**What's the difference between `workTime` and `remoteWork`?** `workTime` is the employment *schedule* (full-time / part-time / occasional), shown on every card as "en temps plein/partiel/occasionnel". `remoteWork` is a separate, independent axis — how much of the job is done remotely ("Télétravail complet/partiel/occasionnel") — shown as its own optional clause only when the recruiter discloses it. A job can be full-time (`workTime`) AND hybrid-remote (`remoteWork`) at the same time; filter on whichever axis matches your need (`employmentType` input filters `workTime`, `remoteWork` input filters `remoteWork`).

**Why do some jobs have no `salary`?** Most French employers don't disclose a salary range publicly; the field is only populated when HelloWork shows one on the listing.

**Why do some jobs have no `department`?** `department` is only derived when `location` follows the standard "City - NN" pattern. Broader locations (a region name, "France", or a foreign country) don't have a single department to extract.

**Why do some jobs have no `remoteWork`?** The télétravail clause only appears on the card when the recruiter explicitly discloses a remote-work frequency; a missing value doesn't necessarily mean "no remote work" — it may simply be undisclosed at the search-results level.

**How fresh is the data?** HelloWork re-indexes continuously as employers post and remove listings; running the actor gives you the current live listing set for your filters.

**Does `maxItems` guarantee that many results?** No — it's a cap. If fewer jobs match your filters, you'll get fewer records.

**What does `postedDate` mean if HelloWork only shows relative text like "3 days ago"?** `postedDate` is an approximate UTC timestamp computed from that relative text at scrape time; `postedDateRelative` preserves HelloWork's original wording.

**Why do `experienceLevels`, `companyTypes`, and `csrLabels` filter results but not appear as output fields?** HelloWork only shows these attributes on each job's individual detail page, not on the search-results card the actor reads. The filters still narrow which jobs are returned — just visit a result's `url` to see the matching attribute on the live listing.

**Does `radiusKm` work with a `region` filter?** No — the radius only applies around a specific `city`. A region has no single center point to measure a radius from, so `radiusKm` is ignored unless `city` is set.

**Does `minSalary` exclude jobs that don't disclose a salary?** No — it only excludes jobs that disclose a salary *below* the floor. Jobs with no disclosed salary still pass through. Combine with `salaryOnly: true` if you want disclosed-only, above-floor results.

**Does this actor fetch each job's full description page?** No — all output fields come from the search-results listing cards, which keeps runs fast. Fields only shown on a job's detail page (full description text, required diploma, application instructions) are not included; use the `url` field to open the full listing.

# Actor input Schema

## `mode` (type: `string`):

What to fetch.

## `searchQuery` (type: `string`):

Free-text keyword search (job title, skill, company, etc.) (mode=search). Can be combined with the filters below.

## `region` (type: `string`):

French administrative region to browse jobs in. Required for mode=byLocation unless `city` is set; optional filter on other modes.

## `city` (type: `string`):

French city or commune name to browse jobs in (e.g. `Lyon`, `Bordeaux`). Takes priority over `region` when both are set. Required for mode=byLocation unless `region` is set; optional filter on other modes.

## `sector` (type: `string`):

Industry sector to browse jobs in. Required for mode=bySector unless `jobFunction` is set; optional filter on other modes.

## `jobFunction` (type: `string`):

Job function (métier) to browse jobs in. Alternative/complement to `sector` for mode=bySector; optional filter on other modes.

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

Filter by one or more contract types (optional, all modes).

## `remoteWork` (type: `array`):

Filter by disclosed remote-work (télétravail) frequency (optional, all modes).

## `employmentType` (type: `array`):

Filter by employment schedule -- full-time vs part-time (optional, all modes).

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

Filter by the years of experience the employer asks for (optional, all modes).

## `companyTypes` (type: `array`):

Filter by the type of hiring organization (optional, all modes).

## `csrLabels` (type: `array`):

Filter to employers holding a specific CSR (corporate social responsibility) certification (optional, all modes).

## `minSalary` (type: `integer`):

Only include jobs whose disclosed salary meets this yearly gross EUR floor (optional, all modes). Matches HelloWork's own "Salaire minimum" slider (0-100,000, steps of 1,000).

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

Widen or narrow the search radius around `city` (ignored when only `region` is set -- HelloWork's radius filter only applies to a specific city/commune).

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

Only include jobs posted within this time window (optional, all modes).

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

Result ordering.

## `salaryOnly` (type: `boolean`):

Only include job listings that disclose a salary range (optional, all modes).

## `superRecruiterOnly` (type: `boolean`):

Only include job listings from HelloWork-verified "super recruiter" companies (optional, all modes).

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

Hard cap on the number of job listings to emit.

## Actor input object example

```json
{
  "mode": "search",
  "searchQuery": "developpeur",
  "region": "",
  "city": "",
  "sector": "",
  "jobFunction": "",
  "contractTypes": [],
  "remoteWork": [],
  "employmentType": [],
  "experienceLevels": [],
  "companyTypes": [],
  "csrLabels": [],
  "minSalary": 0,
  "radiusKm": "20",
  "postedWithin": "all",
  "sortBy": "relevance",
  "salaryOnly": false,
  "superRecruiterOnly": false,
  "maxItems": 30
}
```

# Actor output Schema

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

Dataset containing all scraped HelloWork job listings.

# 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 = {
    "mode": "search",
    "searchQuery": "developpeur",
    "region": "",
    "city": "",
    "sector": "",
    "jobFunction": "",
    "contractTypes": [],
    "remoteWork": [],
    "employmentType": [],
    "experienceLevels": [],
    "companyTypes": [],
    "csrLabels": [],
    "minSalary": 0,
    "radiusKm": "20",
    "postedWithin": "all",
    "sortBy": "relevance",
    "salaryOnly": false,
    "superRecruiterOnly": false,
    "maxItems": 30
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlerbros/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 = {
    "mode": "search",
    "searchQuery": "developpeur",
    "region": "",
    "city": "",
    "sector": "",
    "jobFunction": "",
    "contractTypes": [],
    "remoteWork": [],
    "employmentType": [],
    "experienceLevels": [],
    "companyTypes": [],
    "csrLabels": [],
    "minSalary": 0,
    "radiusKm": "20",
    "postedWithin": "all",
    "sortBy": "relevance",
    "salaryOnly": False,
    "superRecruiterOnly": False,
    "maxItems": 30,
}

# Run the Actor and wait for it to finish
run = client.actor("crawlerbros/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 '{
  "mode": "search",
  "searchQuery": "developpeur",
  "region": "",
  "city": "",
  "sector": "",
  "jobFunction": "",
  "contractTypes": [],
  "remoteWork": [],
  "employmentType": [],
  "experienceLevels": [],
  "companyTypes": [],
  "csrLabels": [],
  "minSalary": 0,
  "radiusKm": "20",
  "postedWithin": "all",
  "sortBy": "relevance",
  "salaryOnly": false,
  "superRecruiterOnly": false,
  "maxItems": 30
}' |
apify call crawlerbros/hellowork-jobs-scraper --silent --output-dataset

```

## MCP server setup

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