# HelloWork Jobs Scraper — Salaries & Company Data (`haketa/hellowork-jobs-scraper`) Actor

Scrape current HelloWork jobs across France with salaries, contracts, remote status, locations, skills, full descriptions, requirements, company profiles and job URLs. Search multiple keywords and cities, apply flexible filters, and export clean French recruitment data to JSON, CSV or Excel.

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

## Pricing

from $1.00 / 1,000 results

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

<h1 align="center">🇫🇷 HelloWork Jobs Scraper — Salaries, Details & Companies</h1>

<p align="center">
  Turn French job listings into clean, structured recruitment data — in minutes.
</p>

<p align="center">
  <img src="https://img.shields.io/badge/FRANCE-JOBS-0055A4?style=for-the-badge" alt="France jobs">
  <img src="https://img.shields.io/badge/NO--CODE-READY-7C3AED?style=for-the-badge" alt="No code">
  <img src="https://img.shields.io/badge/FULL-JOB-DETAILS-16A34A?style=for-the-badge" alt="Full details">
  <img src="https://img.shields.io/badge/EXPORT-JSON%20%7C%20CSV%20%7C%20EXCEL-F59E0B?style=for-the-badge" alt="Export formats">
</p>

### ⚡ At a glance

| | What you get |
|---|---|
| 🔎 Search | Multiple job keywords × multiple French locations |
| 💼 Job data | Title, company, contract, location, remote status and URLs |
| 💶 Salary data | Published salary ranges plus available estimates |
| 📝 Rich details | Full description, requirements, skills and education |
| 🏢 Company data | Company page, logo, industry and hiring identity |
| 🚀 Performance | Fast HTTP collection without a heavy browser |
| 📦 Delivery | JSON, CSV, Excel, XML and API-ready dataset |

> 💡 Add several keywords and locations to discover more jobs in one run. Each keyword is combined with each location automatically.

### What does this HelloWork scraper do?

HelloWork Jobs Scraper collects current French job opportunities and converts them into consistent records ready for analysis, recruitment workflows, lead generation or job aggregation.

You can search roles such as:

- software developer in Paris;
- sales representative in Lyon;
- nurse in Marseille;
- data analyst across France;
- alternance and internship opportunities;
- remote and hybrid jobs;
- jobs with published salary information.

The Actor supports two useful collection modes:

| Mode | Best for | Speed | Data depth |
|---|---|---:|---:|
| ⚡ Overview | Monitoring, discovery and large exports | Fastest | Core listing fields |
| ✨ Enriched | Recruiting, matching and market intelligence | Fast | Full job and company fields |

Overview mode saves the information visible in search results. Enriched mode visits each selected job and adds descriptions, skills, requirements, precise dates and company metadata.

### Why use it?

French job data is useful only when it is searchable, comparable and ready to integrate. This Actor handles pagination, removes duplicate listings and normalizes the most important fields for you.

You receive:

- one row per unique job;
- stable HelloWork job IDs;
- clean text instead of page clutter;
- structured locations and dates;
- consistent salary values where published;
- source URLs for verification;
- search context for every record;
- timestamps for monitoring freshness.

### 🎯 Popular use cases

| Use case | How the data helps |
|---|---|
| 🧲 Recruitment sourcing | Discover current candidates' target roles and hiring companies |
| 📣 Job aggregation | Feed fresh French vacancies into a job board or newsletter |
| 🏢 Hiring lead generation | Identify companies actively recruiting by role and location |
| 💶 Salary research | Compare advertised compensation across professions and cities |
| 📊 Labor-market analysis | Track demand for skills, occupations and contract types |
| 🧠 AI job matching | Supply structured descriptions and skills to matching models |
| 🔔 Job alerts | Schedule searches and notify users when new jobs appear |
| 🗺️ Regional research | Compare hiring activity across French cities and regions |
| 🎓 Graduate research | Monitor internships, stages and alternance opportunities |
| 🧾 CRM enrichment | Add hiring signals and current roles to company records |

#### Recruiting teams

Build targeted vacancy lists using title, skills, contract, location and freshness. Enriched records include enough context to prioritize opportunities without opening every page manually.

#### Job boards and newsletters

Collect a repeatable feed for a niche profession, region or contract type. Schedule the Actor and connect the dataset to your publishing workflow.

#### Sales and lead-generation teams

Open jobs are strong hiring signals. Search for roles connected to your product, then use company identity, industry and source links to qualify accounts.

#### Analysts and researchers

Compare salary visibility, remote-work adoption, skills demand and regional distribution using normalized fields that work in spreadsheets and BI tools.

### 🚀 Quick start

1. Open the Actor input.
2. Enter one or more job keywords.
3. Enter locations, or leave locations empty for France-wide results.
4. Choose optional filters.
5. Set the maximum number of jobs.
6. Click **Start**.
7. Export the dataset in your preferred format.

The prefilled example searches for **développeur jobs in Paris** and is intentionally limited for a quick first run.

### Input options

| Input | Type | Default | Purpose |
|---|---|---:|---|
| `searchKeywords` | String list | `développeur` | Professions, titles or skills to search |
| `locations` | String list | `Paris` | Cities, departments or regions |
| `startUrls` | URL list | Empty | Direct job pages or custom search pages |
| `contractTypes` | Select list | All | CDI, CDD, interim, stage, alternance and more |
| `remoteOnly` | Boolean | `false` | Keep only jobs mentioning remote work |
| `postedWithinDays` | Integer | `0` | Keep only recent jobs; zero disables it |
| `minSalary` | Integer | `0` | Minimum published annual salary threshold |
| `includeDetails` | Boolean | `true` | Add full job and company fields |
| `includeDescriptionHtml` | Boolean | `false` | Keep formatted description HTML |
| `maxItems` | Integer | `1000` | Maximum unique jobs saved |
| `maxConcurrency` | Integer | `8` | Parallel detail requests |
| `proxyConfiguration` | Object | Direct | Optional proxy configuration |

#### Search more data

The Actor creates every keyword and location combination.

For example:

```json
{
  "searchKeywords": ["développeur", "data analyst", "product manager"],
  "locations": ["Paris", "Lyon", "Bordeaux"],
  "maxItems": 1000,
  "includeDetails": true
}
```

This creates nine targeted searches while still deduplicating jobs that appear more than once.

#### Search all of France

Use an empty location value:

```json
{
  "searchKeywords": ["commercial"],
  "locations": [""],
  "maxItems": 500
}
```

#### Search contract types

```json
{
  "searchKeywords": ["marketing"],
  "locations": ["France"],
  "contractTypes": ["CDI", "Alternance"],
  "maxItems": 500
}
```

#### Collect remote jobs

```json
{
  "searchKeywords": ["software engineer", "devops"],
  "locations": ["France"],
  "remoteOnly": true,
  "includeDetails": true,
  "maxItems": 300
}
```

#### Fast overview export

```json
{
  "searchKeywords": ["infirmier"],
  "locations": ["Paris", "Lyon", "Marseille"],
  "includeDetails": false,
  "maxItems": 2000
}
```

> 💡 Use overview mode for frequent large monitoring runs. Enable enrichment when descriptions, skills and precise metadata matter.

### Output fields

#### 💼 Job identity

| Field | Meaning | Coverage |
|---|---|---|
| `jobId` | Stable listing identifier | 🟢 Nearly every record |
| `title` | Job title | 🟢 Nearly every record |
| `url` | Canonical job URL | 🟢 Nearly every record |
| `reference` | Employer or listing reference | 🟡 When published |
| `datePosted` | Publication date | 🟢 Nearly every record |
| `validThrough` | Advertised expiration date | 🟡 When available |
| `scrapedAt` | Collection timestamp | 🟢 Every record |

#### 🏢 Company intelligence

| Field | Meaning | Coverage |
|---|---|---|
| `company` | Hiring company | 🟢 Most records |
| `companyConfidential` | Anonymous-employer indicator | 🟢 Every record |
| `companyUrl` | Company profile URL | 🟢 Most enriched records |
| `companyLogoUrl` | Company logo URL | 🟡 When available |
| `industry` | Employer industry labels | 🟡 When published |

#### 📍 Location and work model

| Field | Meaning | Coverage |
|---|---|---|
| `location` | Display location | 🟢 Nearly every record |
| `city` | Locality | 🟢 Enriched records |
| `postalCode` | Postal code | 🟡 When available |
| `region` | French region | 🟢 Enriched records |
| `countryCode` | Country code, normally `FR` | 🟢 Enriched records |
| `remoteWork` | Remote or hybrid label | 🟡 When offered |

#### 📄 Employment and profession

| Field | Meaning | Coverage |
|---|---|---|
| `contractType` | CDI, CDD, alternance, stage and more | 🟢 Nearly every record |
| `employmentType` | Structured employment type | 🟢 Enriched records |
| `profession` | Normalized profession category | 🟡 Enriched records |
| `jobDomain` | Job domain | 🟡 Enriched records |
| `jobFunction` | Functional category | 🟡 Enriched records |
| `occupationalCategory` | Occupational family | 🟡 Enriched records |

#### 💶 Salary data

| Field | Meaning | Coverage |
|---|---|---|
| `salaryText` | Original published salary label | 🟡 When published |
| `salaryMin` | Parsed lower bound | 🟡 When published |
| `salaryMax` | Parsed upper bound | 🟡 When published |
| `salaryCurrency` | Salary currency | 🟡 When published |
| `salaryPeriod` | Year, month, day or hour | 🟡 When published |
| `estimatedSalaryMedian` | Available market estimate | 🟡 Enriched records |
| `estimatedSalaryMin` | Lower estimate | 🟡 Enriched records |
| `estimatedSalaryMax` | Upper estimate | 🟡 Enriched records |

Published salary and estimated salary are separate fields so your analysis never confuses employer-provided compensation with an estimate.

#### 🧠 Matching and content

| Field | Meaning | Coverage |
|---|---|---|
| `description` | Full clean job description | 🟢 Enriched records |
| `descriptionHtml` | Optional formatted description | ⚪ Only when requested |
| `requirements` | Candidate qualifications | 🟢 Most enriched records |
| `skills` | Structured skills | 🟢 Most enriched records |
| `tags` | Searchable job tags | 🟢 Enriched records |
| `educationRequirements` | Education levels | 🟡 When published |
| `experienceRequirements` | Experience statement | 🟡 When published |

#### 🔎 Search context

| Field | Meaning |
|---|---|
| `searchKeyword` | Keyword that discovered the job |
| `searchLocation` | Location that discovered the job |
| `searchPage` | Search-result page number |
| `detailEnriched` | Whether the full detail page was processed |
| `directApply` | Whether a direct application flow is indicated |
| `applicationType` | Available application route classification |

### Example result

```json
{
  "jobId": "77194876",
  "title": "Concepteur - Développeur H/F",
  "company": "Groupe NGE",
  "location": "Paris - 75000",
  "city": "Paris",
  "region": "Île-de-France",
  "countryCode": "FR",
  "contractType": "CDI",
  "employmentType": "FULL_TIME",
  "remoteWork": null,
  "industry": ["BTP"],
  "skills": ["SQL", "Python", "Java", "C#"],
  "datePosted": "2026-07-26T00:10:31.000Z",
  "companyUrl": "https://www.hellowork.com/fr-fr/entreprises/example.html",
  "url": "https://www.hellowork.com/fr-fr/emplois/example.html",
  "detailEnriched": true
}
```

Actual fields vary because employers decide which salary, education, remote-work and company information they publish.

### Data quality

The Actor is designed around practical dataset quality:

- duplicate jobs are removed by stable job ID;
- relative search dates are upgraded to precise dates during enrichment;
- salary text remains available alongside parsed numbers;
- anonymous employers are explicitly marked;
- missing optional values remain empty instead of being invented;
- source URLs are retained for auditing;
- failed individual enrichments fall back to the overview record;
- records include the time at which they were collected.

### Integrations

Connect results to:

- Google Sheets;
- Airtable;
- Zapier;
- Make;
- Slack;
- webhooks;
- REST API clients;
- Python or JavaScript workflows;
- data warehouses;
- CRM and ATS systems;
- AI and retrieval pipelines.

#### API usage

Run the Actor with the Apify API or an Apify client and read records from the default dataset. The same input fields available in the Console can be sent as JSON.

<details>
<summary><strong>JavaScript client example</strong></summary>

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('YOUR_USERNAME/hellowork-jobs-scraper').call({
  searchKeywords: ['data analyst'],
  locations: ['Paris', 'Lyon'],
  includeDetails: true,
  maxItems: 250
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

</details>

<details>
<summary><strong>Python client example</strong></summary>

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("YOUR_USERNAME/hellowork-jobs-scraper").call(run_input={
    "searchKeywords": ["commercial"],
    "locations": ["Bordeaux", "Toulouse"],
    "includeDetails": True,
    "maxItems": 250,
})

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

</details>

### Scheduling fresh job data

For monitoring, create an Apify schedule and run the same input daily or weekly. Use a webhook or integration to forward new datasets to your workflow.

Useful schedules include:

- daily remote developer jobs;
- weekly salary snapshots;
- new alternance listings every morning;
- regional healthcare openings;
- competitor hiring signals;
- company-specific recruitment monitoring.

### Performance and cost tips

#### For the fastest run

- disable `includeDetails`;
- search one focused keyword and location;
- keep the direct connection unless it is blocked;
- use a realistic `maxItems` limit.

#### For the richest data

- enable `includeDetails`;
- keep `maxConcurrency` between 6 and 12;
- use several relevant keyword-location combinations;
- request description HTML only if formatting is required.

#### For broad discovery

- add several keywords;
- add major cities and regions;
- leave contract filters empty;
- increase `maxItems`;
- rely on automatic deduplication.

### Honest limitations

- Data availability depends on active public listings.
- Some employers intentionally hide their company name.
- Salary is not published for every job.
- Remote-work wording differs between employers.
- Estimated salary fields are not employer guarantees.
- Closed or expired listings can disappear between search and enrichment.
- Very broad searches may contain overlapping listings; duplicates are removed.
- The Actor does not submit applications or contact employers.

### FAQ

#### Do I need to code?

No. Fill in the input form and click Start. Coding is optional for API integrations.

#### Can I scrape multiple cities?

Yes. Add each city to `locations`. Every location is combined with every keyword.

#### Can I search all of France?

Yes. Leave the location list empty or use an empty location value.

#### Can I collect CDI, CDD, stage or alternance jobs?

Yes. Use the contract selector to choose one or more supported contract types.

#### Does it return salary data?

Yes, when salary information is available. Published and estimated salaries remain separate.

#### Does it return full descriptions?

Yes. Keep `includeDetails` enabled.

#### Does it collect skills?

Yes. Enriched results include structured skills when available.

#### Can it find remote jobs?

Yes. Enable `remoteOnly` to keep listings that mention remote work.

#### Are duplicate jobs removed?

Yes. Records are deduplicated by the stable job ID across pages and search combinations.

#### Can I use direct job URLs?

Yes. Add individual HelloWork job URLs to `startUrls`.

#### Can I use an existing search URL?

Yes. Add the search URL to `startUrls`. It runs alongside keyword searches.

#### Which export formats are supported?

Apify datasets can be downloaded as JSON, CSV, Excel, XML and other supported formats.

#### How many jobs can I collect?

Set `maxItems` to the number you need. Actual availability depends on the searches and active listings.

#### Why is a company missing?

Some postings are intentionally anonymous. The `companyConfidential` field identifies these records.

#### Why is salary missing?

Employers do not always publish compensation. The Actor never fabricates a salary.

#### Should I enable a proxy?

Usually no. Direct collection is the fastest and lowest-cost choice. A proxy remains available if your environment needs it.

#### Can I schedule the Actor?

Yes. Apify schedules can run it automatically at the frequency you choose.

#### Can I connect it to an AI workflow?

Yes. The structured description, skills, title and location fields are suitable for search, classification and matching pipelines.

#### Does this Actor apply for jobs?

No. It collects public job information only.

### Tips for better searches

- Use French role names for the broadest local coverage.
- Try both a role and its common English equivalent.
- Split broad searches by major city to increase useful coverage.
- Use contract filters for dedicated internship or alternance datasets.
- Keep enrichment enabled for semantic matching and lead qualification.
- Keep overview mode for frequent discovery runs.
- Use `postedWithinDays` for alert-style workflows.
- Use `minSalary` only when missing-salary jobs should be excluded.

### Responsible use

This Actor collects publicly available job information. Use the data responsibly and comply with applicable laws, contractual obligations, privacy requirements and the source website's terms. Do not use collected data for spam, discrimination or unlawful automated decision-making.

HelloWork is a trademark of its respective owner. This Actor is an independent tool and is not affiliated with, endorsed by or sponsored by HelloWork.

### Support

If a page layout changes or a field you need is missing, open an issue from the Actor page with:

- the input used;
- an example listing URL;
- the run ID;
- the expected field;
- a short description of the problem.

Please do not include API tokens, passwords, cookies or personal credentials.

***

<p align="center"><strong>Collect French jobs. Understand hiring demand. Build faster.</strong></p>

# Actor input Schema

## `searchKeywords` (type: `array`):

Jobs, skills or professions to search. Every keyword is combined with every location, so adding more values returns more opportunities.

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

French cities, departments or regions. Leave empty for France-wide results. Each location creates an additional search.

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

Optional HelloWork search pages or individual job URLs. These run in addition to keyword searches.

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

Select one or more contract types. Leave empty to include every contract.

## `remoteOnly` (type: `boolean`):

Keep only listings that mention full, partial or occasional remote work.

## `postedWithinDays` (type: `integer`):

Keep only recently posted jobs. Use 0 to disable this filter.

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

Keep jobs whose published maximum annual salary reaches this value. Jobs without salary data are excluded when set. Use 0 for no filter.

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

Visit each job page for full description, requirements, skills, precise publication date, company profile, salary estimates and application metadata.

## `includeDescriptionHtml` (type: `boolean`):

Add the original formatted HTML alongside clean text when detail enrichment is enabled.

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

Total number of unique jobs saved across all searches. Increase this to collect more data in one run.

## `maxConcurrency` (type: `integer`):

Recommended range: 6–12. Higher values may be faster but place more load on the source.

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

Direct requests are fastest and cheapest. Enable Apify Proxy only if your network is blocked.

## Actor input object example

```json
{
  "searchKeywords": [
    "data analyst",
    "commercial",
    "infirmier"
  ],
  "locations": [
    "Paris",
    "Lyon",
    "Bordeaux"
  ],
  "startUrls": [],
  "contractTypes": [],
  "remoteOnly": false,
  "postedWithinDays": 0,
  "minSalary": 0,
  "includeDetails": true,
  "includeDescriptionHtml": false,
  "maxItems": 50,
  "maxConcurrency": 8,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `dataset` (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 = {
    "searchKeywords": [
        "développeur"
    ],
    "locations": [
        "Paris"
    ],
    "startUrls": [],
    "contractTypes": [],
    "includeDetails": false,
    "maxItems": 50,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("haketa/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 = {
    "searchKeywords": ["développeur"],
    "locations": ["Paris"],
    "startUrls": [],
    "contractTypes": [],
    "includeDetails": False,
    "maxItems": 50,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("haketa/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 '{
  "searchKeywords": [
    "développeur"
  ],
  "locations": [
    "Paris"
  ],
  "startUrls": [],
  "contractTypes": [],
  "includeDetails": false,
  "maxItems": 50,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call haketa/hellowork-jobs-scraper --silent --output-dataset

```

## MCP server setup

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