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

\[💰 $0.95 / 1K] Extract job listings from HelloWork — France's leading job board. Search by keyword and city, filter by contract type, telework, and date posted, and get titles, companies, salaries, full descriptions, and apply links.

- **URL**: https://apify.com/solidcode/hellowork-scraper.md
- **Developed by:** [SolidCode](https://apify.com/solidcode) (community)
- **Categories:** Jobs, Automation, Developer tools
- **Stats:** 3 total users, 1 monthly users, 100.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.95 / 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 a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

Pull job listings from HelloWork — France's leading job board — at scale, complete with French-format salary ranges, contract codes (CDI / CDD / Alternance / Stage / Intérim / Freelance), telework mode, hiring company, sector, full descriptions, and ISO-8601 posted dates. Built for French recruiters, EU talent-acquisition teams, and salary-benchmarking analysts who need clean, structured French job-market data without parsing HelloWork's French HTML one page at a time.

### Why This Scraper?

- **Six French contract types in one filter** — CDI (permanent), CDD (fixed-term), Alternance (work-study), Stage (internship), Intérim (temporary), and Freelance / Indépendant. The biggest filter facet on HelloWork, exposed as a multi-select.
- **Four telework modes** — Full remote (télétravail complet), Partial, Occasional, and On-site only. Filter the French remote-job market without learning the French labels.
- **Parsed salary ranges in euros** — every row carries `salaryMin`, `salaryMax`, `salaryCurrency` (EUR), and `salaryPeriod` (YEAR / MONTH / DAY / HOUR), parsed from French formats like `50 000 - 55 000 € / an` including narrow no-break-space thousand separators.
- **Five recency windows** — Any time, Last 24 hours, Last 3 days, Last 7 days, or Last 30 days. Surface only fresh leads when you need them.
- **Minimum annual salary filter** — set `minSalary: 60000` and HelloWork constrains the search server-side before pagination starts.
- **Multi-keyword + multi-URL batch input** — run `["développeur", "data engineer", "product manager"]` in one go, or paste any HelloWork search URLs you already built in the UI. Mix both in the same run.
- **Up to 5,000 jobs per search** — sustained pagination across HelloWork's ~30-per-page SERP, with overshoot-don't-trim semantics that keep your final page whole.
- **Structured detail extraction** — title, hiring company, full HTML and plain-text description, 200-character snippet, required skills array, sector (Services aux Entreprises, Tech, etc.), education and experience requirements, valid-through date, and stable HelloWork `jobId` on every row.

### Use Cases

**Recruitment & Talent Sourcing**
- Build a target-company list of every employer hiring CDI développeurs in Île-de-France this week
- Track Alternance and Stage postings across France for student-pipeline programs
- Find freelance and Intérim opportunities matched to specific skill sets

**Salary Benchmarking**
- Build EUR salary bands per role and city from parsed `salaryMin` / `salaryMax` ranges
- Compare CDI vs. Freelance compensation for the same job title
- Track salary inflation over time by re-running the same query monthly

**Market & Competitive Intelligence**
- Monitor which French companies are hiring fastest in your sector
- Benchmark competitor headcount expansion by counting active listings per employer
- Detect emerging skill demand by skill-array frequency across thousands of rows

**Lead Generation**
- Surface hiring companies for B2B HR-tech, recruitment, or training sales
- Filter to companies posting 10+ open roles — high-intent buyers for talent solutions
- Build region-targeted prospect lists by French département or region

**Job Aggregation & Vertical Search**
- Power a niche French job board or Slack alert bot with fresh HelloWork listings
- Feed jobs into a CRM, ATS, or candidate-matching engine via webhook
- De-duplicate against your existing dataset using stable `jobId` values

### Getting Started

#### Basic Search

The simplest possible run — one keyword, one city:

```json
{
    "searchQueries": ["développeur"],
    "location": "Paris",
    "maxResults": 50
}
````

#### Filtered Search (Contract + Telework + Recency)

Fresh permanent and freelance full-remote roles posted in the last week:

```json
{
    "searchQueries": ["data engineer", "data scientist"],
    "location": "Lyon",
    "contractType": ["CDI", "FREELANCE"],
    "telework": ["FULL", "PARTIAL"],
    "datePosted": "1w",
    "minSalary": 55000,
    "maxResults": 200,
    "includeJobDetails": true
}
```

#### Paste a Pre-Built HelloWork URL

Already built a search with custom filters in the HelloWork UI? Paste the URL directly:

```json
{
    "startUrls": [
        "https://www.hellowork.com/fr-fr/emploi/recherche.html?k=chef+de+projet&l=Toulouse&c=CDI",
        "https://www.hellowork.com/fr-fr/emploi/recherche.html?k=comptable&l=Bordeaux"
    ],
    "maxResults": 500
}
```

### Input Reference

#### Search

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `searchQueries` | string\[] | `["développeur"]` | Job titles or keyword phrases such as `développeur`, `comptable`, or `chef de projet`. Each entry runs its own search. |
| `location` | string | `"Paris"` | City, département, or region in France (e.g. `Paris`, `Lyon`, `Marseille`, `Île-de-France`). Applied to every keyword. Leave blank to search the whole country. |
| `startUrls` | string\[] | `[]` | Optional. Paste full HelloWork search URLs to use them as-is. Useful when you've already built a search with custom filters in the HelloWork UI. |

#### Filters & Limits

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `maxResults` | integer | `100` | Maximum jobs per keyword or URL. Use `50` for a quick scan, `500` for deep research. Set to `0` for no cap (an internal upper limit of 5,000 still applies). The actor keeps the full final page even if it slightly overshoots. |
| `contractType` | select\[] | `[]` | Only return jobs matching these contract types: `CDI`, `CDD`, `ALTERNANCE`, `STAGE`, `INTERIM`, `FREELANCE`. Empty = all types. |
| `telework` | select\[] | `[]` | Filter by remote work mode: `FULL`, `PARTIAL`, `OCCASIONAL`, `NONE` (on-site only). Empty = all modes. |
| `datePosted` | select | `"any"` | Only include jobs posted within: `any`, `24h`, `3d`, `1w`, or `1m`. |
| `minSalary` | integer | null | Only return jobs offering at least this annual salary in euros. Listings without a posted salary are still included. |

#### Output

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `includeJobDetails` | boolean | `true` | Fetch the full description, skills, sector, and structured posting metadata from each job's detail page. Disable for faster light scans that return only the search-card data. |

### Output

Each row is a single job. Here's a representative result with full details enabled. Most fields populate when the employer fills them in on HelloWork; `salary*`, `skills`, `experience`, `telework`, and `sector` can be `null` / `[]` when not provided.

```json
{
    "title": "Développeur Python H/F",
    "company": "Team.is",
    "companyUrl": "https://www.hellowork.com/fr-fr/entreprises/teamis-101426.html",
    "companyLogo": "https://f.hellowork.com/img/entreprises/160_160/teamis.png",
    "location": "Paris 1er - 75",
    "city": "Paris 1er",
    "postalCode": "75001",
    "region": "Île-de-France",
    "country": "France",
    "salary": "50 000 - 55 000 € / an",
    "salaryMin": 50000,
    "salaryMax": 55000,
    "salaryCurrency": "EUR",
    "salaryPeriod": "YEAR",
    "contractType": "CDI",
    "employmentTypeRaw": "CDI",
    "employmentTypeEnum": "FULL_TIME",
    "telework": "FULL",
    "datePosted": "2026-05-13",
    "validThrough": "2026-06-12",
    "skills": ["Python", "Django", "PostgreSQL"],
    "qualifications": "Bac +5 ou équivalent en informatique ...",
    "education": "Bac +3, Bac +4",
    "experience": "3 ans",
    "sector": "Banque/Assurance/Finance",
    "descriptionHtml": "<p>Nous recherchons un développeur expérimenté...</p>",
    "descriptionText": "Nous recherchons un développeur expérimenté...",
    "snippet": "Nous recherchons un développeur expérimenté pour rejoindre notre équipe Python...",
    "jobId": "75605607",
    "jobUrl": "https://www.hellowork.com/fr-fr/emplois/75605607.html",
    "listPageUrl": "https://www.hellowork.com/fr-fr/emploi/recherche.html?k=developpeur&l=Paris",
    "searchQuery": "développeur",
    "scrapedAt": "2026-05-16T11:46:58Z"
}
```

#### Core Fields

| Field | Type | Description |
|-------|------|-------------|
| `title` | string | Job title (often ends with " H/F" — French equal-opportunity convention). |
| `company` | string | Hiring company name. |
| `companyUrl` | string | Company website when shown on HelloWork. |
| `companyLogo` | string | Logo image URL when available. |
| `jobId` | string | Stable HelloWork numeric ID — perfect for deduplication. |
| `jobUrl` | string | Canonical detail-page URL. |
| `listPageUrl` | string | Originating search URL. |
| `searchQuery` | string | Which keyword produced this row. |
| `scrapedAt` | string | ISO-8601 UTC timestamp of extraction. |

#### Location

| Field | Type | Description |
|-------|------|-------------|
| `location` | string | Full location string as displayed. |
| `city` | string | Parsed city. |
| `postalCode` | string | French postal code (e.g. `75001`). |
| `region` | string | French region (e.g. `Île-de-France`, `Auvergne-Rhône-Alpes`). |
| `country` | string | Always `France`. |

#### Salary & Contract

| Field | Type | Description |
|-------|------|-------------|
| `salary` | string | Raw salary string as displayed on HelloWork. |
| `salaryMin` | number | Lower bound parsed in EUR. |
| `salaryMax` | number | Upper bound parsed in EUR. |
| `salaryCurrency` | string | Currency code — always `EUR` in practice. |
| `salaryPeriod` | string | Pay period — `YEAR`, `MONTH`, `DAY`, or `HOUR`. |
| `contractType` | string | Normalized contract code: `CDI`, `CDD`, `ALTERNANCE`, `STAGE`, `INTERIM`, or `FREELANCE`. |
| `employmentTypeRaw` | string | Original French contract label as shown on HelloWork (e.g. `CDI`, `Alternance`, `Intérim`). |
| `employmentTypeEnum` | string | Google JSON-LD enum (`FULL_TIME`, `PART_TIME`, `INTERN`, `TEMPORARY`, `CONTRACTOR`) for integrations that expect the standard code. |
| `telework` | string | Remote work mode: `FULL` when the listing is fully remote, `null` otherwise. Round-trips with the `telework` input filter. |
| `datePosted` | string | ISO-8601 publication date. |
| `validThrough` | string | ISO-8601 date the listing expires. |

#### Description & Detail

| Field | Type | Description |
|-------|------|-------------|
| `descriptionHtml` | string | Full job description in HTML markup. Populated when `includeJobDetails` is on. |
| `descriptionText` | string | Full job description as plain text. |
| `snippet` | string | 200-character preview for quick scanning. |
| `skills` | string\[] | Required skills extracted from the structured posting. Empty when HelloWork doesn't expose a structured skill list for the role. |
| `qualifications` | string | Qualifications text. |
| `education` | string | Education level (e.g. `Master`, `Bac +5`, `Bac +3, Bac +4`). |
| `experience` | string | Experience required as a French label (e.g. `1 an`, `3 ans`, `Sans expérience requise`). |
| `sector` | string | Industry / sector (e.g. `Banque/Assurance/Finance`, `Services aux Entreprises`). |

### Tips for Best Results

- **Mix `searchQueries` and `startUrls` in one run.** Pay for one start and get both a fresh keyword sweep and any pre-filtered URLs you've built in the HelloWork UI — sector pages, RSE-label searches, or autocomplete pages with no equivalent filter input. Results are deduplicated across all sources by `jobId`, so the same posting only appears once in the dataset even when it surfaces in multiple keywords.
- **Use the French label.** HelloWork is a French-only site — `développeur` returns thousands of hits, `developer` returns a handful. The same applies for cities: `Lyon` works, `Lyons` does not.
- **For full coverage of Paris, run per-arrondissement.** Paris alone has 20 arrondissements (`Paris 1er`, `Paris 2e`, ..., `Paris 20e`) — splitting the query is the cleanest way to push past the per-search soft cap.
- **Combine `contractType: ["ALTERNANCE", "STAGE"]` for student pipelines.** These two French-specific contracts cover work-study and internships — the entire early-career recruitment funnel in one filter.
- **Turn off `includeJobDetails` for fast scans.** When you only need title / company / salary for a market sweep, disabling detail fetches skips one request per job and roughly halves run time.
- **Use `datePosted: "24h"` for daily alerts.** Pair with a webhook to push every new posting matching your filters into Slack, email, or your ATS.
- **Deduplicate by `jobId`.** HelloWork sometimes repeats the same listing across overlapping searches — the numeric `jobId` is stable across runs, so use it as your dedupe key.

### Pricing

**$0.95 per 1,000 results** — flat per-row pricing, slightly below the market rate for French job-board extraction.

| Results | Estimated Cost |
|---------|----------------|
| 100 | $0.10 |
| 1,000 | $0.95 |
| 10,000 | $9.50 |
| 100,000 | $95.00 |

A "result" is one job row in the output dataset. **No compute charges — you only pay per result returned.** Apify platform fees (storage, transfer) are additional and depend on your plan.

### Integrations

Export data in JSON, CSV, Excel, XML, or RSS. Connect to 1,500+ apps via:

- **Zapier** / **Make** / **n8n** — Workflow automation
- **Google Sheets** — Direct spreadsheet export
- **Slack** / **Email** — Notifications on new results
- **Webhooks** — Trigger custom APIs on run completion
- **Apify API** — Full programmatic access

### Legal & Ethical Use

This actor is designed for legitimate recruitment research, salary benchmarking, market intelligence, and job aggregation use cases. Users are responsible for complying with applicable laws — including French and EU data protection rules (RGPD/GDPR) — and with HelloWork's terms of service. Make reasonable-rate requests, respect content usage rules for any descriptions or company data extracted, and do not use the data for spam, harassment, or any illegal purpose.

# Actor input Schema

## `searchQueries` (type: `array`):

Job titles or keyword phrases to search for, such as 'développeur', 'comptable', or 'chef de projet'. Each entry runs a separate search. Leave empty if you only want to use direct HelloWork URLs.

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

City, département, or region in France (e.g., Paris, Lyon, Marseille, Île-de-France). Applied to every keyword above. Leave blank to search the whole country.

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

Optional. Paste full HelloWork job search URLs (e.g., https://www.hellowork.com/fr-fr/emploi/recherche.html?k=developpeur\&l=Paris) to use them as-is. Useful when you've already built a search with custom filters in the HelloWork UI.

## `maxResults` (type: `integer`):

Maximum jobs to collect per search keyword or URL. Use 50 for a quick scan, 500 for deep research. Set to 0 for no cap (an internal upper limit of 5,000 still applies to prevent runaway pagination). The actor stops requesting new pages once this number is reached but keeps the full final page even if it slightly overshoots.

## `contractType` (type: `array`):

Only return jobs matching these French contract types. Leave empty for all types.

## `telework` (type: `array`):

Filter by remote work mode. Leave empty for all.

## `datePosted` (type: `string`):

Only include jobs posted within this window.

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

Only return jobs offering at least this annual salary in euros. Leave blank to apply no salary filter. Note: many HelloWork listings omit a salary — those rows are still included even when this filter is set.

## `includeJobDetails` (type: `boolean`):

Fetch the full description, skills, sector, and structured posting metadata from each job's detail page. Slightly slower but produces much richer data. Disable for faster light scans that return only the search-card data.

## Actor input object example

```json
{
  "searchQueries": [
    "développeur"
  ],
  "location": "Paris",
  "startUrls": [],
  "maxResults": 100,
  "contractType": [],
  "telework": [],
  "datePosted": "any",
  "includeJobDetails": true
}
```

# Actor output Schema

## `overview` (type: `string`):

Table of scraped job listings with key fields.

## `detail` (type: `string`):

Complete job records including descriptions and salary breakdowns.

# 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 = {
    "searchQueries": [
        "développeur"
    ],
    "location": "Paris",
    "startUrls": [],
    "maxResults": 100,
    "contractType": [],
    "telework": [],
    "datePosted": "any",
    "includeJobDetails": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("solidcode/hellowork-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 = {
    "searchQueries": ["développeur"],
    "location": "Paris",
    "startUrls": [],
    "maxResults": 100,
    "contractType": [],
    "telework": [],
    "datePosted": "any",
    "includeJobDetails": True,
}

# Run the Actor and wait for it to finish
run = client.actor("solidcode/hellowork-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchQueries": [
    "développeur"
  ],
  "location": "Paris",
  "startUrls": [],
  "maxResults": 100,
  "contractType": [],
  "telework": [],
  "datePosted": "any",
  "includeJobDetails": true
}' |
apify call solidcode/hellowork-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=solidcode/hellowork-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "HelloWork Jobs Scraper",
        "description": "[💰 $0.95 / 1K] Extract job listings from HelloWork — France's leading job board. Search by keyword and city, filter by contract type, telework, and date posted, and get titles, companies, salaries, full descriptions, and apply links.",
        "version": "1.0",
        "x-build-id": "NOvnvif8x6gPFzqz3"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/solidcode~hellowork-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-solidcode-hellowork-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/solidcode~hellowork-scraper/runs": {
            "post": {
                "operationId": "runs-sync-solidcode-hellowork-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/solidcode~hellowork-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-solidcode-hellowork-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "searchQueries": {
                        "title": "Search Keywords",
                        "type": "array",
                        "description": "Job titles or keyword phrases to search for, such as 'développeur', 'comptable', or 'chef de projet'. Each entry runs a separate search. Leave empty if you only want to use direct HelloWork URLs.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "location": {
                        "title": "Location",
                        "type": "string",
                        "description": "City, département, or region in France (e.g., Paris, Lyon, Marseille, Île-de-France). Applied to every keyword above. Leave blank to search the whole country."
                    },
                    "startUrls": {
                        "title": "Direct HelloWork Search URLs",
                        "type": "array",
                        "description": "Optional. Paste full HelloWork job search URLs (e.g., https://www.hellowork.com/fr-fr/emploi/recherche.html?k=developpeur&l=Paris) to use them as-is. Useful when you've already built a search with custom filters in the HelloWork UI.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxResults": {
                        "title": "Max Results per Search",
                        "minimum": 0,
                        "maximum": 5000,
                        "type": "integer",
                        "description": "Maximum jobs to collect per search keyword or URL. Use 50 for a quick scan, 500 for deep research. Set to 0 for no cap (an internal upper limit of 5,000 still applies to prevent runaway pagination). The actor stops requesting new pages once this number is reached but keeps the full final page even if it slightly overshoots.",
                        "default": 100
                    },
                    "contractType": {
                        "title": "Contract Type",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Only return jobs matching these French contract types. Leave empty for all types.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "CDI",
                                "CDD",
                                "ALTERNANCE",
                                "STAGE",
                                "INTERIM",
                                "FREELANCE"
                            ],
                            "enumTitles": [
                                "CDI (permanent)",
                                "CDD (fixed-term)",
                                "Alternance (apprenticeship / work-study)",
                                "Stage (internship)",
                                "Intérim (temporary)",
                                "Freelance / Indépendant"
                            ]
                        },
                        "default": []
                    },
                    "telework": {
                        "title": "Remote / Telework",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Filter by remote work mode. Leave empty for all.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "FULL",
                                "PARTIAL",
                                "OCCASIONAL",
                                "NONE"
                            ],
                            "enumTitles": [
                                "Full remote (télétravail complet)",
                                "Partial (télétravail partiel)",
                                "Occasional (télétravail occasionnel)",
                                "On-site only (pas de télétravail)"
                            ]
                        },
                        "default": []
                    },
                    "datePosted": {
                        "title": "Date Posted",
                        "enum": [
                            "any",
                            "24h",
                            "3d",
                            "1w",
                            "1m"
                        ],
                        "type": "string",
                        "description": "Only include jobs posted within this window.",
                        "default": "any"
                    },
                    "minSalary": {
                        "title": "Minimum Annual Salary (EUR)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Only return jobs offering at least this annual salary in euros. Leave blank to apply no salary filter. Note: many HelloWork listings omit a salary — those rows are still included even when this filter is set."
                    },
                    "includeJobDetails": {
                        "title": "Include Full Job Details",
                        "type": "boolean",
                        "description": "Fetch the full description, skills, sector, and structured posting metadata from each job's detail page. Slightly slower but produces much richer data. Disable for faster light scans that return only the search-card data.",
                        "default": true
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
