HelloWork Jobs Scraper API - France Job Board avatar

HelloWork Jobs Scraper API - France Job Board

Pricing

from $0.48 / 1,000 jobs

Go to Apify Store
HelloWork Jobs Scraper API - France Job Board

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

Dami's Studio

Maintained by Community

Actor stats

0

Bookmarked

8

Total users

6

Monthly active users

a day ago

Last modified

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.

InputJob keywords and a French location, or HelloWork URLs
OutputOne row per posting: title, company, city, department, contract, salary with its source, posted date, skills
Ceiling20,000 postings per run
Account neededNone
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 getField
HelloWork's posting id, title, company and linksjobId, title, companyName, jobUrl, companyProfileUrl
Where it islocationLabel, city, departmentCode, region, postalCode, countryCode
Contract, its length, working timecontractType, contractDuration, employmentType, workingTime
The télétravail band and two flagsteleworkLabel, isRemote, isHybrid
The salary, and whether HelloWork estimated itsalaryMin, salaryMax, salaryCurrency, salaryPeriod, salaryText, salaryIsEstimate
HelloWork's estimate on its ownsalaryEstimateMin, salaryEstimateMedian, salaryEstimateMax
Posted and expiry datespostedAt, postedRelative, postedAtEstimated, expiresAt
Category, sectors, skills, education, experienceoccupationalCategory, sectors, skills, educationLevels, experienceRequired
The employer's reference and direct applyreference, directApply
The full posting text, when you ask for itdescriptionHtml, descriptionText, requirementsText
Where the row came fromsearchQuery, page, position, scrapedAt

▶️ How to scrape HelloWork jobs

  1. Open HelloWork Jobs Scraper and click Try for free.
  2. Put your terms into Job keywords, one per line.
  3. Add a Location and a radius if you want it local.
  4. Set Maximum postings, then click Start.
  5. 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
}
FieldDefaultWhat it is
searchQueriesnoneOne or more searches. The box starts with développeur in it, which is a suggestion and not a default.
locationnoneA city, department or region: Paris, Lyon, Île-de-France. Empty searches the whole country.
radiusKmnoneKilometres around the location, 1 to 200. Only used when a location is set.
contractTypesallcdi, cdd, interim, stage, alternance, freelance, independant, fonctionnaire, franchise, associe, stage-lycee.
teleworkallfull, partial, occasional, none. Only about 18% of postings carry any remote tag, so this one narrows hard.
workingTimeallfull-time, part-time, unspecified.
experienceallHelloWork's bands: 0-1, 2-3, 4-5, 6-10, 10+, unspecified.
employerTypeallcompany, agency, consultancy, temp-agency, training-centre.
postedWithinany timeday, 3days, week, month.
minSalarynoneYearly 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.
onlyWithSalaryfalseAsk HelloWork for postings that display a salary. Leaving it off returns more rows, and only about 63% of them carry one.
sortByrelevancerelevance or date.
startUrlsnonePaste HelloWork URLs instead of building a search. A single posting works, and so does a search page.
includeDetailstrueOpen each posting for the full record.
includeDescriptionfalseAdd 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.
maxItems50Stop after this many distinct postings, up to 20,000.
proxyConfigurationnoneLeave 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.

FieldHow to read it
salaryIsEstimatefalse 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.
departmentCodeThe French department number, 75 for Paris, 69 for Lyon, 56 for Morbihan.
contractTypeCDI, CDD, Intérim, Stage, Alternance, Freelance and the rest. contractDuration carries 6 mois and the like on fixed terms.
teleworkLabelHelloWork'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.
postedAtThe exact timestamp, and it only exists when postings are opened. On a listing-only run you get postedRelative and postedAtEstimated instead.
expiresAtWhen HelloWork takes the posting down.
descriptionHtml, descriptionText, requirementsTextOnly filled in when you switch the full description on.
detailNotePresent 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

RowHow to spot itCharged
A postingIt has a jobIdyes
A posting whose page could not be read, or with no titleA jobId, detailNote and charged: falseno
The sample row_sample: true and charged: falseno
A diagnosticAn errorCode and no jobIdno
errorCodeWhat it means
NO_RESULTSThe search ran and matched nothing. Loosen a filter or try a broader keyword.
BAD_URLA pasted URL is not a HelloWork posting or search page.
JOB_NOT_FOUNDThat posting is gone. Expired postings do this.
JOB_UNPARSEDThe page could not be read. Re-run it.
HTTP_ERRORHelloWork answered badly or was unreachable.
TIME_LIMITThe 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 === false so the numbers are the ones employers actually printed.
  • Watching one city and one contract type daily, with postedWithin set to day, and deduping on jobId, which is stable.
  • Mapping demand by department, since every row carries departmentCode and most carry a postal code.
  • Pulling the skills arrays 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. salaryIsEstimate is the only thing that tells you apart.
  • minSalary filters 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. expiresAt tells you when, and a pasted link to a dead posting returns JOB_NOT_FOUND.
  • Listing-only runs have no exact posted date. Turn postings on if you need postedAt rather than postedAtEstimated.
  • 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 wantUse
French postings from HelloWork, with the salary marked real or estimatedThis one
Public LinkedIn jobs by keyword and locationLinkedIn Jobs Scraper
Arbeitnow's postings for Germany, the UK, France and Switzerland, with its visa-sponsorship flagArbeitnow Jobs Scraper
Jobs in Germany, Austria and Switzerland, marked remote, hybrid or on-siteXING Jobs Scraper
Every open job at companies you name, read from their own hiring systemCareer 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.

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.