HelloWork Jobs Scraper API - France Job Board
Pricing
from $0.48 / 1,000 jobs
HelloWork Jobs Scraper API - France Job Board
Scrape HelloWork jobs in France by keyword and city. Each row has the title, company, city and department, the contract (CDI, CDD, intérim, stage, alternance), skills, posted date and salary. A flag says when the salary is HelloWork's own estimate. $0.49 per 1,000 postings.
Pricing
from $0.48 / 1,000 jobs
Rating
0.0
(0)
Developer
Dami's Studio
Maintained by CommunityActor stats
0
Bookmarked
8
Total users
6
Monthly active users
a day ago
Last modified
Categories
Share
Scrape HelloWork jobs in France, with the contract type and a salary marked real or estimated: search by keyword and city, filter by contract, remote band, experience or salary, and get rows back with the title, company, city and department, CDI or CDD or intérim or stage or alternance, the salary, the posted date and the link.
The salary field needs a warning before anything else. When an employer publishes no figure,
HelloWork fills the gap with its own estimate. Both arrive in the same place, so every row carries
salaryIsEstimate and you should read it before you treat a number as an offer.
| Input | Job keywords and a French location, or HelloWork URLs |
| Output | One row per posting: title, company, city, department, contract, salary with its source, posted date, skills |
| Ceiling | 20,000 postings per run |
| Account needed | None |
| Price | $0.49 per 1,000 postings on the Free plan, a little less on paid plans. The free plan's $5 a month covers about 10,000 |
🔍 What HelloWork Jobs Scraper does
Each keyword you give it is walked as its own search, so ["développeur", "data analyst"] runs two.
French terms work best, and English job titles match plenty of postings too. Add a city, department
or region and a radius in kilometres to keep it local.
These filters from HelloWork's own sidebar are here: contract type, télétravail band, working time,
experience, who is hiring, posted-within window and a minimum salary. Broad searches repeat rows
across pages, and duplicates are removed before anything counts toward your maximum, so maxItems
means distinct postings.
By default each posting's own page is opened, which is where the exact posted date, the expiry date, the postal code and region, the sector, the skills list and the education level come from. Turn that off for a faster listing-only run and you keep title, company, location, contract, salary and an approximate posted date.
📋 What data you get from each HelloWork posting
| What you get | Field |
|---|---|
| HelloWork's posting id, title, company and links | jobId, title, companyName, jobUrl, companyProfileUrl |
| Where it is | locationLabel, city, departmentCode, region, postalCode, countryCode |
| Contract, its length, working time | contractType, contractDuration, employmentType, workingTime |
| The télétravail band and two flags | teleworkLabel, isRemote, isHybrid |
| The salary, and whether HelloWork estimated it | salaryMin, salaryMax, salaryCurrency, salaryPeriod, salaryText, salaryIsEstimate |
| HelloWork's estimate on its own | salaryEstimateMin, salaryEstimateMedian, salaryEstimateMax |
| Posted and expiry dates | postedAt, postedRelative, postedAtEstimated, expiresAt |
| Category, sectors, skills, education, experience | occupationalCategory, sectors, skills, educationLevels, experienceRequired |
| The employer's reference and direct apply | reference, directApply |
| The full posting text, when you ask for it | descriptionHtml, descriptionText, requirementsText |
| Where the row came from | searchQuery, page, position, scrapedAt |
▶️ How to scrape HelloWork jobs
- Open HelloWork Jobs Scraper and click Try for free.
- Put your terms into Job keywords, one per line.
- Add a Location and a radius if you want it local.
- Set Maximum postings, then click Start.
- Download the dataset as JSON, CSV or Excel, or read it from the Apify API.
💰 How much does it cost to scrape HelloWork jobs?
$0.49 per 1,000 postings on the Free plan. Paid plans pay a little less: $0.485 on Starter, $0.48 on Scale and $0.475 on Business. On the free plan, the $5 Apify gives you each month covers about 10,000 postings.
You pay per posting row. Duplicates across pages are dropped before they count, the sample row is
not charged, and diagnostic rows are not charged. Adding the full description does not add a second
charge, it only makes the rows bigger. A posting whose own page could not be read still arrives as a
row, with its listing fields, detailNote and charged: false, and is not charged. So does a posting
that comes without a job title.
📥 What you give it
{"searchQueries": ["comptable"],"location": "Lyon","radiusKm": 20,"contractTypes": ["cdi"],"onlyWithSalary": true,"maxItems": 200}
| Field | Default | What it is |
|---|---|---|
searchQueries | none | One or more searches. The box starts with développeur in it, which is a suggestion and not a default. |
location | none | A city, department or region: Paris, Lyon, Île-de-France. Empty searches the whole country. |
radiusKm | none | Kilometres around the location, 1 to 200. Only used when a location is set. |
contractTypes | all | cdi, cdd, interim, stage, alternance, freelance, independant, fonctionnaire, franchise, associe, stage-lycee. |
telework | all | full, partial, occasional, none. Only about 18% of postings carry any remote tag, so this one narrows hard. |
workingTime | all | full-time, part-time, unspecified. |
experience | all | HelloWork's bands: 0-1, 2-3, 4-5, 6-10, 10+, unspecified. |
employerType | all | company, agency, consultancy, temp-agency, training-centre. |
postedWithin | any time | day, 3days, week, month. |
minSalary | none | Yearly euros. HelloWork applies this to its own estimate as well as to published figures, so pair it with the next field if you want real offers. |
onlyWithSalary | false | Ask HelloWork for postings that display a salary. Leaving it off returns more rows, and only about 63% of them carry one. |
sortBy | relevance | relevance or date. |
startUrls | none | Paste HelloWork URLs instead of building a search. A single posting works, and so does a search page. |
includeDetails | true | Open each posting for the full record. |
includeDescription | false | Add the whole posting text as HTML and plain text plus the requirements section. Needs includeDetails on. It rides on the same request, so it adds no time and no charge. |
maxItems | 50 | Stop after this many distinct postings, up to 20,000. |
proxyConfiguration | none | Leave it alone. Your own servers are used exactly as given. |
📤 What you get back
A real row from a run on 20 September 2026. Note salaryIsEstimate, because this one is
HelloWork's estimate rather than the employer's figure:
{"jobId": "80369776","title": "Développeur H/F","companyName": "Neqo","jobUrl": "https://www.hellowork.com/fr-fr/emplois/80369776.html","companyProfileUrl": "https://www.hellowork.com/fr-fr/entreprises/neqo-133722.html","locationLabel": "Vannes - 56","city": "Vannes","departmentCode": "56","region": "Bretagne","postalCode": "56000","countryCode": "FR","contractType": "CDI","contractDuration": null,"employmentType": "FULL_TIME","workingTime": "Full time","teleworkLabel": "Hybrid","isRemote": false,"isHybrid": true,"salaryMin": 28000,"salaryMax": 44000,"salaryCurrency": "EUR","salaryPeriod": "YEAR","salaryText": "28000 - 44000 EUR / year","salaryIsEstimate": true,"salaryEstimateMin": 28000,"salaryEstimateMedian": 37500,"salaryEstimateMax": 44000,"postedAt": "2026-09-18T00:13:47Z","postedRelative": "il y a 2 jours","postedAtEstimated": "2026-09-18T07:03:19.923Z","expiresAt": "2026-10-18T00:13:47Z","occupationalCategory": "Informatique","sectors": ["Secteur informatique", "ESN"],"skills": ["Service client", "SQL", "CakePHP", "Git", "HTML5", "Node.js", "PHP", "MySQL", "..."],"educationLevels": ["bachelor degree", "associate degree"],"experienceRequired": null,"reference": "3937186/29254901 D/56V","directApply": true,"searchQuery": "développeur","page": 1,"position": 2,"scrapedAt": "2026-09-20T07:03:35.992Z"}
The skills list is cut short; the real row carries sixteen.
| Field | How to read it |
|---|---|
salaryIsEstimate | false means the employer published the figure. true means it is HelloWork's own estimate for that title and region, and the same numbers are repeated in the salaryEstimate* fields so one filter drops them. null means no salary at all. If you only want real offers, keep salaryIsEstimate === false. |
departmentCode | The French department number, 75 for Paris, 69 for Lyon, 56 for Morbihan. |
contractType | CDI, CDD, Intérim, Stage, Alternance, Freelance and the rest. contractDuration carries 6 mois and the like on fixed terms. |
teleworkLabel | HelloWork's own télétravail band, and mostly empty because most employers do not set one. isRemote and isHybrid are the flags derived from it. |
postedAt | The exact timestamp, and it only exists when postings are opened. On a listing-only run you get postedRelative and postedAtEstimated instead. |
expiresAt | When HelloWork takes the posting down. |
descriptionHtml, descriptionText, requirementsText | Only filled in when you switch the full description on. |
detailNote | Present when the posting page could not be read, or when the posting came without a title. That row keeps its listing fields, carries charged: false and is not charged. |
🧾 Reading the output
| Row | How to spot it | Charged |
|---|---|---|
| A posting | It has a jobId | yes |
| A posting whose page could not be read, or with no title | A jobId, detailNote and charged: false | no |
| The sample row | _sample: true and charged: false | no |
| A diagnostic | An errorCode and no jobId | no |
errorCode | What it means |
|---|---|
NO_RESULTS | The search ran and matched nothing. Loosen a filter or try a broader keyword. |
BAD_URL | A pasted URL is not a HelloWork posting or search page. |
JOB_NOT_FOUND | That posting is gone. Expired postings do this. |
JOB_UNPARSED | The page could not be read. Re-run it. |
HTTP_ERROR | HelloWork answered badly or was unreachable. |
TIME_LIMIT | The run reached its time limit and stopped on its own. The jobs already returned are kept and charged; give the run more time to get the rest. The run ends as failed only when the time limit stopped it before any job came back. |
💡 What people use it for
- Salary research that survives scrutiny, by keeping only
salaryIsEstimate === falseso the numbers are the ones employers actually printed. - Watching one city and one contract type daily, with
postedWithinset today, and deduping onjobId, which is stable. - Mapping demand by department, since every row carries
departmentCodeand most carry a postal code. - Pulling the
skillsarrays for a role across a few hundred postings to see which tools keep appearing. - Telling employers apart from agencies with
employerType, which changes what a listing count actually means.
🚧 What it does not do
- France only. That is HelloWork's own coverage.
- The salary can be an estimate. HelloWork produces one when the employer published nothing,
and it lands in the same fields.
salaryIsEstimateis the only thing that tells you apart. minSalaryfilters estimates too. HelloWork applies its own filter to its own estimate, so a high minimum still returns postings with no published figure. Combine it with Only postings that show a salary.- The remote band is usually empty. Only about 18% of postings carry one, so filtering on it cuts results hard and drops postings that are remote but untagged.
- No applications, no candidate data, no recruiter contact details. Postings only.
- A single search runs out before the cap. Going wide means several keywords, cities or
filters, not a bigger
maxItems. - Pasted postings arrive at the end of the run. 10,000 pasted URLs took about 29 minutes, and nothing from a paste is written until it finishes, so keep big lists in a few runs.
- Postings expire.
expiresAttells you when, and a pasted link to a dead posting returnsJOB_NOT_FOUND. - Listing-only runs have no exact posted date. Turn postings on if you need
postedAtrather thanpostedAtEstimated. - It is not an official HelloWork tool. Dami's Studio is independent and is not affiliated with or endorsed by HelloWork, or by any other company named on this page.
🧭 Which job scraper do you need?
| If you want | Use |
|---|---|
| French postings from HelloWork, with the salary marked real or estimated | This one |
| Public LinkedIn jobs by keyword and location | LinkedIn Jobs Scraper |
| Arbeitnow's postings for Germany, the UK, France and Switzerland, with its visa-sponsorship flag | Arbeitnow Jobs Scraper |
| Jobs in Germany, Austria and Switzerland, marked remote, hybrid or on-site | XING Jobs Scraper |
| Every open job at companies you name, read from their own hiring system | Career Site Jobs Scraper |
❓ Questions people ask
Do I need a HelloWork account?
No. Everything here is on public posting pages.
How do I get only real salaries?
Switch on Only postings that show a salary, then keep rows where salaryIsEstimate is false.
The first narrows what HelloWork sends, the second catches the estimates that still come through.
Should I search in French or English?
French matches more. English job titles work for the technical roles that are advertised that way.
Can I paste a single posting?
Yes, into HelloWork URLs. A search page URL works there too.
Why is postedAt empty?
You ran with postings closed. The exact date lives on the posting page.
Can I call it from code or connect it to an AI assistant?
Yes. The API tab has ready-made
code for Python, JavaScript and the command line. For Claude, ChatGPT or another MCP client, connect
https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/hellowork-jobs-scraper. Either way the
run happens on your Apify account at the same price.
Is scraping HelloWork legal?
These are public job adverts, and they can carry personal data, which GDPR covers, so have a reason for collecting it. Apify's write-up on the legality of web scraping is a good starting point, and we are not lawyers.
🆘 If something breaks
Open the Issues tab on the actor page. Send the keyword, the location and the run ID. If you got
a diagnostic row, its errorCode usually names the problem on its own.