Welcome to the Jungle Scraper (WTTJ) | $2/1K Jobs + Apply URLs avatar

Welcome to the Jungle Scraper (WTTJ) | $2/1K Jobs + Apply URLs

Pricing

from $2.00 / 1,000 jobs

Go to Apify Store
Welcome to the Jungle Scraper (WTTJ) | $2/1K Jobs + Apply URLs

Welcome to the Jungle Scraper (WTTJ) | $2/1K Jobs + Apply URLs

Scrape Welcome to the Jungle job listings through the official search API. Full job details, direct ATS apply URLs, company data, 15+ filters, exports beyond the 1000-result limit.

Pricing

from $2.00 / 1,000 jobs

Rating

5.0

(1)

Developer

Alex Morain

Alex Morain

Maintained by Community

Actor stats

0

Bookmarked

3

Total users

1

Monthly active users

15 days ago

Last modified

Share

Welcome to the Jungle Scraper (WTTJ): jobs, apply URLs, company data

Scrape Welcome to the Jungle job listings through the official search API the website itself uses. No headless browser, no HTML parsing, no CSS selectors that break on the next redesign. You get the full listing, the company behind it, and, when the employer uses their own ATS, the direct apply URL.

The corpus is 88,902 live listings as of 5 September 2026, of which 70,853 in France, 16,677 in the United States, 4,750 in the United Kingdom, 1,877 in Canada and the rest spread across Spain, Germany, Belgium, Switzerland, Italy and the Czech Republic. Welcome to the Jungle is the reference job board for French tech and startup hiring, so this is the shortest path to structured recruitment data France-side.

Price: $2 per 1,000 jobs ($0.002 per job), plus $0.00001 per dataset item and $0.00005 per GB of memory to start a run. A 1,000-job export costs about $2.01. Nothing else is billed, and full job details cost the same as titles only.


How to scrape Welcome to the Jungle

From the Apify console

  1. Open the Input tab. Every field is optional and one search is already prefilled, so pressing Start right away gives you 100 jobs and shows the shape of the output.
  2. Replace Search query with your own keyword, or clear it to browse the entire corpus and filter instead. Clearing it is the right move for lead generation, where you want every company hiring in a sector rather than one job title.
  3. Narrow with the filters: country and city, contract type, remote policy, sector, company size, salary floor. They are sent to the Welcome to the Jungle search API before anything is collected, so a narrow search is both faster and cheaper.
  4. Set Max jobs to 0 when you want every matching job rather than a sample. The search API caps any single query at 1,000 results; this Actor detects the cap and splits the export by publication date to walk past it.
  5. Press Start. When the run ends, download the dataset as JSON, CSV or Excel, or read it from the API.

From the API

Every run is a POST to the Apify API with the same input object. The three code examples further down are copy-pastable in Python, JavaScript and cURL. Two things worth knowing before you write the call:

  • run-sync-get-dataset-items returns the results in the HTTP response, which is convenient up to a few thousand jobs. Past that, start the run asynchronously and read the dataset afterwards, because a synchronous call is capped by the request timeout.
  • Add maxTotalChargeUsd to the run parameters to cap what a run may cost. The Actor watches that ceiling and stops cleanly when it is reached, with a log line saying why, instead of failing or silently truncating.

Which fields should I fill?

Nothing is mandatory. An empty input is a valid run: it returns the 100 most relevant jobs of the whole corpus.

If you want to...Fill inLeave empty
Find one type of rolequery, countryCodeseverything else
Build a lead list of companies that hiresectors, companySizeMin / companySizeMax, countryCodesquery
Feed a job board dailypublishedWithinDays: 1, sortBy: "newest"query
Watch specific companiescompanySlugsall other filters
Do salary researchsalaryYearlyMin, professionCategoriesquery
Cover a whole labour marketaroundLatLng, aroundRadiusKmcities
Take a fast inventory of what existsincludeDetails: false, maxItems: 0everything else

Input fields

FieldTypeWhat it doesExample
querystringFree-text search across the whole listing: job title, skill, keyword, company name. Empty means browse the entire corpus."data engineer"
searchOnlyInJobTitlebooleanRestricts the search to job titles. Use it when a common word floods your results: python in full text matches every listing that mentions it in passing.true
resultsLanguagestringLanguage of the localized labels in the output: profession names, skills, sectors. fr, en, es, cs, sk. It does not filter and does not translate the job text."en"
sortBystringrelevance uses the Welcome to the Jungle ranking, newest sorts by publication date. Use newest for recurring runs."newest"
publishedWithinDaysstringPublication window: any, 1, 3, 7, 14, 30."1"
countryCodesarrayISO 3166-1 alpha-2 country codes of the office.["FR", "BE"]
citiesarrayCity of the office, matched exactly on the name as Welcome to the Jungle writes it. A misspelling returns nothing.["Paris", "Lyon"]
aroundLatLngstringSearch around a GPS point, format lat, lng. Catches surrounding towns a city filter would miss."45.7640, 4.8357"
aroundRadiusKmintegerRadius around that point. Defaults to 20 km when a point is set, ignored otherwise.50
contractTypesarrayfull_time (French CDI), part_time, temporary, fixed_term, internship, apprenticeship, freelance, vie, graduate_program, volunteer, other.["apprenticeship"]
remotearrayfulltime, partial, punctual, no, unknown. unknown is frequent and real: many employers leave the field empty.["fulltime"]
jobLanguagesarrayLanguage the listing is written in, a decent proxy for the working language of the team. 15 values from fr to ja.["en"]
maxExperienceRequiredintegerKeeps jobs asking for at most this many years. 0 keeps the roles open to beginners. Listings with no declared level are kept.2
educationLevelsarrayFrench scale: no_diploma, cap, bep, bac, bac_1 to bac_5, phd.["bac_5"]
salaryYearlyMinintegerKeeps jobs whose published yearly minimum is at least this amount. Listings with no salary are excluded, and most have none.50000
sectorsarrayIndustry of the company: tech-1, banking-insurance-finance, consulting-audit, health-social-environment and 16 more.["tech-1"]
professionCategoriesarrayProfession family of the job itself, which is not the company sector: a developer at a bank is Tech & Engineering in Banking.["tech-engineering-3NjUy"]
companySizeMinintegerLower bound on headcount.20
companySizeMaxintegerUpper bound on headcount. With the minimum, this is how you target a segment.200
companySlugsarrayExport every job of named companies, whatever the other filters. Slug from the company URL, or the exact company name.["doctolib", "swile"]
maxItemsintegerCap on jobs returned. 0 exports everything that matches. Default 100.0
includeDetailsbooleanFetches the full listing of every job: description, recruitment process, skills, tools, apply URL, company website and LinkedIn. On by default. Turning it off does not lower the price.true
proxyConfigurationobjectLeave it off. The search API needs no proxy and detail requests are retried automatically. Set a residential proxy only if a large run logs repeated detail failures.{}

What each Welcome to the Jungle job listing contains

Every item in the dataset is one job. The fields below always come back, whatever the value of includeDetails, because they come from the search index in the same pass as the search itself.

Job identity

FieldTypeDescriptionExample
idstringWelcome to the Jungle job UUID, stable across runs."73fb7661-cded-4c5b-b3a2-9a8e99ffa513"
titlestringJob title as published."Data Engineer (H/F)"
urlstringListing page on welcometothejungle.com, in the language set by resultsLanguage."https://www.welcometothejungle.com/fr/companies/link-consulting/jobs/data-engineer-h-f_toulouse_LC_x9OYDZY"
slugstringJob slug, the last path segment of the URL."data-engineer-h-f_toulouse_LC_x9OYDZY"
referencestringInternal Welcome to the Jungle reference, equal to id in practice."73fb7661-cded-4c5b-b3a2-9a8e99ffa513"
wttjReferencestringShort public reference shown on the listing."LC_x9OYDZY"
publishedAtstringISO 8601 publication date. Renewing a listing refreshes it, so treat it as "last put forward", not "first published"."2026-09-05T00:02:36Z"
languagestringLanguage the listing is written in."fr"
scrapedAtstringISO 8601 timestamp of collection."2026-09-05T13:31:25.639Z"

Contract, seniority, salary

FieldTypeDescriptionExample
contractTypestringOne of the eleven contract values listed in the input table."full_time"
contractDurationMinMonthsintegerMinimum contract duration in months, for fixed-term and apprenticeships.24
contractDurationMaxMonthsintegerMaximum contract duration in months.null
remotestringfulltime, partial, punctual, no or unknown."partial"
experienceMinYearsintegerMinimum years of experience required, null when not declared.4
educationLevelstringRequired diploma on the French scale."bac_5"
salaryMinintegerLower bound of the published salary, in the unit given by salaryPeriod.500
salaryMaxintegerUpper bound.550
salaryCurrencystringCurrency of the published figures."EUR"
salaryPeriodstringyearly, monthly or daily. Daily rates are common on freelance and consulting listings."daily"
salaryYearlyMinintegerYearly minimum normalized by Welcome to the Jungle, which is what makes daily and monthly rates comparable. This is the field the salaryYearlyMin filter compares against.109000
salaryTextstringReady-to-display string built from the four fields above."500-550 EUR/daily"

Classification

FieldTypeDescriptionExample
professionCategorystringProfession family, localized."Technologie et ingénierie"
professionSubCategorystringSub-family."Données/Business Intelligence"
professionstringNormalized job title, useful to group listings that spell the same role differently."Ingénieur de données"
sectorsarraySectors of the company, localized.["Recrutement", "Digital"]

Location

FieldTypeDescriptionExample
officesarrayOne object per office: city, state, district, country, countryCode. A job can be attached to several.[{"city": "Toulouse", "state": "Occitanie", "district": "Haute-Garonne", "country": "France", "countryCode": "FR"}]
citiesstringComma-joined, deduplicated city names, for spreadsheets that dislike nested arrays."Lille, Suresnes"
geolocarrayGPS coordinates of each office, lat and lng.[{"lat": 43.61199, "lng": 1.44334}]

Content of the listing

FieldTypeDescriptionExample
summarystringShort plain-text summary written by Welcome to the Jungle."Rejoignez Link Consulting, une entreprise qui valorise..."
keyMissionsarrayThree or four sentences describing the actual work.["Concevoir et fiabiliser les flux de transformation / ETL..."]
profilestringCandidate profile the employer is asking for, HTML."<p>De formation supérieure Bac+5...</p>"
benefitsarrayPerks declared by the company: remote days, meal vouchers, profit sharing, health cover.["Horaires de travail flexibles", "Prime de cooptation"]

Welcome to the Jungle company data

FieldTypeDescriptionExample
companyNamestringCompany name."Link Consulting"
companySlugstringCompany slug, the identifier to pass back in companySlugs."link-consulting"
companySummarystringOne-line company pitch."Cabinet de conseil en recrutement et assistance technique IT."
companyLogostringCDN URL of the logo."https://cdn-images.welcometothejungle.com/..."
companyLabelsarrayCertifications and awards claimed on the profile.["happy-index-at-work", "we-impact-index"]
companyNbEmployeesintegerHeadcount.80

Fields that need includeDetails: true

These come from a second request per job, against the public Welcome to the Jungle jobs API. They are the reason the Actor exists, which is why the option is on by default.

FieldTypeDescriptionExample
applyUrlstringDirect ATS apply URL on the employer's own system, bypassing the Welcome to the Jungle listing page. null when the employer uses the built-in Welcome to the Jungle ATS."https://jobaffinity.fr/apply/n9owui5rph70kedm0p?src=WelcometotheJungle"
atsstringWhich application route the employer uses: external (their own ATS), kombo (an ATS connected through an integration), wkit (Welcome to the Jungle's own kit, no external URL)."external"
descriptionstringFull job description, HTML."<p>Notre client, acteur industriel...</p>"
recruitmentProcessstringInterview steps as published by the employer, HTML. Filled in on a minority of listings."<p>1. LE MATCHING...</p>"
companyDescriptionstringLong company description, HTML, when the employer wrote one.null
startDatestringDeclared start date."2026-10-01"
updatedAtstringISO 8601 timestamp of the last edit to the listing."2026-09-05T00:02:36.690111Z"
skillsarraySkills tagged by Welcome to the Jungle, localized.["Intégration continue", "Gestion de la documentation"]
toolsarrayTools and technologies named in the listing.["Azure Data Factory", "Power BI", "SQL", "Talend"]
officeAddressstringStreet address of the office of this job, deduplicated against city and country so it never reads "Toulouse, France, 31000 Toulouse, FR"."15 Rue de Verdun, 31000 Toulouse, France"
applicationFieldsarrayWhat the employer asks a candidate to submit: name and mode (mandatory or optional). Disabled fields are dropped.[{"name": "resume", "mode": "mandatory"}, {"name": "cover_letter", "mode": "optional"}]
companyWebsitestringCompany website."https://link-consulting.fr/"
companyLinkedinstringCompany LinkedIn page, normalized to a full URL."https://www.linkedin.com/company/sas-link-consulting/"
companyIndustrystringIndustry labels in English, whatever resultsLanguage says."Recruitment, Digital"
companyCreationYearintegerYear the company was founded.2016
companyJobsCountintegerNumber of jobs the company currently has open on Welcome to the Jungle. A blunt but effective hiring-intensity signal.83
companyAverageAgeintegerAverage age of employees, when the company published it.34
companyRevenuestringRevenue as written on the company profile, free text."35M € depuis 2016"
companyHeadquarterstringHeadquarters address."15, Rue de Verdun, 31000 Toulouse, FR"

Output example

One real item, collected on 5 September 2026 with includeDetails: true. The long HTML strings are cut short here; in the dataset they are complete.

{
"id": "73fb7661-cded-4c5b-b3a2-9a8e99ffa513",
"title": "Data Engineer (H/F)",
"url": "https://www.welcometothejungle.com/fr/companies/link-consulting/jobs/data-engineer-h-f_toulouse_LC_x9OYDZY",
"applyUrl": "https://jobaffinity.fr/apply/n9owui5rph70kedm0p?src=WelcometotheJungle",
"publishedAt": "2026-09-05T00:02:36Z",
"language": "fr",
"contractType": "full_time",
"contractDurationMinMonths": null,
"contractDurationMaxMonths": null,
"remote": "partial",
"educationLevel": "bac_5",
"experienceMinYears": null,
"salaryMin": 500,
"salaryMax": 550,
"salaryCurrency": "EUR",
"salaryPeriod": "daily",
"salaryYearlyMin": 109000,
"salaryText": "500-550 EUR/daily",
"professionCategory": "Technologie et ingénierie",
"professionSubCategory": "Données/Business Intelligence",
"profession": "Ingénieur de données",
"sectors": ["Recrutement", "Digital"],
"offices": [
{
"city": "Toulouse",
"state": "Occitanie",
"district": "Haute-Garonne",
"country": "France",
"countryCode": "FR"
}
],
"cities": "Toulouse",
"geoloc": [{ "lat": 43.61199, "lng": 1.44334 }],
"summary": "Rejoignez Link Consulting, une entreprise qui valorise l'humilité et le savoir-être. En tant que Data Engineer, vous serez intégré à l'équipe Data BI...",
"keyMissions": [
"Produire des livrables concrets et directement exploitables en intégrant et en consolidant les données issues des différents ERP.",
"Concevoir et fiabiliser les flux de transformation / ETL, et structurer le datawarehouse et les datamarts.",
"Produire la documentation technique et fonctionnelle associée, et faire évoluer les modèles de données."
],
"profile": "<p>De formation supérieure Bac+5, vous justifiez d'une expérience réussie de minimum 3 ans sur des fonctions de Data Engineer...</p>",
"benefits": [
"Horaires de travail flexibles",
"Ouvert au télétravail total",
"Entre 1-2 jours de télétravail",
"Congés payés supplémentaires",
"Prime de cooptation",
"Subventions CSE (Sport, Culture,...)",
"Chèques cadeaux",
"Team building",
"Mentorat",
"Coaching"
],
"companyName": "Link Consulting",
"companySlug": "link-consulting",
"companySummary": "Cabinet de conseil en recrutement et assistance technique IT.",
"companyLogo": "https://cdn-images.welcometothejungle.com/uvTN4ji9y1K14S3VsDwbjPEqlwFZCYYD5_qBavrue-s/rs:auto:400::/q:85/...",
"companyLabels": ["happy-index-at-work", "we-impact-index"],
"companyNbEmployees": 80,
"reference": "73fb7661-cded-4c5b-b3a2-9a8e99ffa513",
"wttjReference": "LC_x9OYDZY",
"slug": "data-engineer-h-f_toulouse_LC_x9OYDZY",
"scrapedAt": "2026-09-05T13:31:25.639Z",
"ats": "external",
"description": "<p>Notre client, acteur industriel dans le secteur de l'aéronautique, recherche son futur Data Engineer (H/F) à Toulouse...</p>",
"recruitmentProcess": null,
"companyDescription": null,
"startDate": null,
"updatedAt": "2026-09-05T00:02:36.690111Z",
"skills": [
"Aptitudes à motiver les autres",
"Gestion de la documentation",
"Intégration continue",
"Aptitude à résoudre les problèmes"
],
"tools": ["Azure Data Factory", "Power BI", "SQL", "Talend"],
"officeAddress": "15 Rue de Verdun, 31000 Toulouse, France",
"applicationFields": [
{ "name": "resume", "mode": "mandatory" },
{ "name": "cover_letter", "mode": "optional" },
{ "name": "picture", "mode": "optional" },
{ "name": "media_website", "mode": "optional" },
{ "name": "media_linkedin", "mode": "optional" },
{ "name": "media_twitter", "mode": "optional" }
],
"companyWebsite": "https://link-consulting.fr/",
"companyLinkedin": "https://www.linkedin.com/company/sas-link-consulting/",
"companyIndustry": "Recruitment, Digital",
"companyCreationYear": 2016,
"companyJobsCount": 83,
"companyAverageAge": null,
"companyRevenue": "35M € depuis 2016",
"companyHeadquarter": "15, Rue de Verdun, 31000 Toulouse, FR"
}

Input examples

Every fully remote permanent tech job in France paying at least 50k, all of them:

{
"countryCodes": ["FR"],
"contractTypes": ["full_time"],
"remote": ["fulltime"],
"sectors": ["tech-1"],
"salaryYearlyMin": 50000,
"maxItems": 0
}

Keyword search around a GPS point, 50 km around Lyon:

{
"query": "data engineer",
"aroundLatLng": "45.7640, 4.8357",
"aroundRadiusKm": 50,
"maxItems": 200
}

Everything three named companies are currently hiring for:

{
"companySlugs": ["doctolib", "swile", "pennylane"],
"maxItems": 0
}

Yesterday's new listings only, for a daily scheduled run:

{
"publishedWithinDays": "1",
"sortBy": "newest",
"countryCodes": ["FR"],
"maxItems": 0
}

Call the Welcome to the Jungle jobs API from code

Python

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run_input = {
"query": "data engineer",
"countryCodes": ["FR"],
"contractTypes": ["full_time"],
"remote": ["fulltime", "partial"],
"salaryYearlyMin": 45000,
"maxItems": 500,
"includeDetails": True,
}
run = client.actor("alexmorain/wttj-jobs-scraper").call(run_input=run_input)
for job in client.dataset(run["defaultDatasetId"]).iterate_items():
print(job["title"], "|", job["companyName"], "|", job["cities"], "|", job["applyUrl"])

Straight into a DataFrame, for salary or market analysis:

import pandas as pd
from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("alexmorain/wttj-jobs-scraper").call(run_input={
"professionCategories": ["tech-engineering-3NjUy"],
"countryCodes": ["FR"],
"salaryYearlyMin": 1,
"includeDetails": False,
"maxItems": 0,
})
df = pd.DataFrame(client.dataset(run["defaultDatasetId"]).list_items().items)
print(df.groupby("professionSubCategory")["salaryYearlyMin"].describe())

JavaScript

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('alexmorain/wttj-jobs-scraper').call({
query: 'product designer',
countryCodes: ['FR'],
publishedWithinDays: '7',
sortBy: 'newest',
maxItems: 300,
includeDetails: true,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const job of items) {
console.log(`${job.title}${job.companyName}${job.applyUrl ?? job.url}`);
}

cURL

Synchronous run, JSON back in the response:

curl -X POST "https://api.apify.com/v2/acts/alexmorain~wttj-jobs-scraper/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"query": "data engineer",
"countryCodes": ["FR"],
"maxItems": 50,
"includeDetails": true
}'

Export WTTJ jobs to CSV

Same call, format=csv on the query string, and the response is a spreadsheet-ready file:

curl -X POST "https://api.apify.com/v2/acts/alexmorain~wttj-jobs-scraper/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>&format=csv" \
-H "Content-Type: application/json" \
-d '{"countryCodes": ["FR"], "sectors": ["tech-1"], "maxItems": 1000}' \
-o wttj-jobs.csv

format also accepts json, jsonl, xlsx, xml and rss. For a large export, start the run asynchronously with POST /v2/acts/alexmorain~wttj-jobs-scraper/runs, then read GET /v2/datasets/<datasetId>/items?format=csv when it finishes. Add &maxTotalChargeUsd=5 to either call to hard-cap what the run may spend.


What people use this scraper for

Candidate sourcing and recruitment data France

Recruiters and agencies use it the other way round from a job seeker: the listing tells you which companies are short of which profiles, right now, with a salary band and a required seniority. Filter on professionCategories and maxExperienceRequired to isolate a segment, and you have the live demand curve for a role in a given city. The tools array is what makes it operational, because it names the actual stack behind a vague title: two listings both called "Data Engineer" split cleanly once one says Databricks and the other says Talend.

Feeding a job board or aggregator

This is the classic French job board scraper use case, and the reason for the publishedWithinDays and sortBy inputs. Schedule a daily run with publishedWithinDays: "1" and sortBy: "newest", which returns roughly 2,700 listings a day across the corpus, and merge them into your own index. Each item carries what a listing page needs: title, company, logo, city, contract, salary string, HTML description, benefits, and a link that sends the candidate either to the employer's ATS or back to Welcome to the Jungle. One caveat worth planning for is that Welcome to the Jungle refreshes publishedAt when an employer renews a listing, so deduplicate on id, not on the date.

B2B prospecting: finding companies that are hiring

A company that opens five roles is a company with a budget and a problem. Leave query empty, set sectors and a headcount range, and the output becomes a lead list rather than a job list: name, website, LinkedIn page, headcount, founding year, headquarters address, self-declared revenue, and companyJobsCount as a rough intensity score. Sales teams selling to HR, to IT, or to any function currently being staffed up can rank prospects by how many roles are open and in which discipline. Deduplicate on companySlug and you have a clean account list.

Tracking the French tech job market

The corpus is large enough to be a real market indicator: 32,922 listings are attached to the Tech sector, and 29,488 across the whole corpus publish a salary. Running the same filtered query on a schedule and storing the counts gives you a time series of demand by profession, by city and by contract type. The contractType breakdown is specific to France and genuinely informative, since apprenticeship listings alone account for 2,765 of the French corpus and behave on a completely different seasonal cycle from permanent roles.

Salary analysis

salaryMin, salaryMax, salaryCurrency and salaryPeriod come straight from the listing, and salaryYearlyMin is the yearly-normalized minimum Welcome to the Jungle computes so that a 550 EUR daily rate and a 42k yearly package can sit in the same column. Combine it with experienceMinYears, educationLevel, remote and cities and you can build a compensation benchmark for a role in a city, which is the sort of dataset consultancies charge for. The honest caveat is in the numbers above: roughly a third of listings publish salary at all, so treat the sample as indicative of the market that discloses, not of the whole market.

Competitive hiring intelligence

Pass a list of competitors, prospects or portfolio companies into companySlugs and the Actor exports every job they currently have open, ignoring the other filters. Watching that list over time tells you which teams they are building, which technologies they are moving to, which cities they are opening, and how fast. The benefits array is an underrated part of this, because it is where remote policy, meal vouchers and equity plans are declared, which is exactly what a competitor's offer looks like from the candidate's side.


Why this Welcome to the Jungle scraper

It uses the Welcome to the Jungle jobs API, not a headless browser

Search runs against the same public search index the website queries, and job details against the same public jobs API endpoint the listing page calls. No Chromium, no page rendering, no waiting on selectors. In a local run on 5 September 2026, 200 jobs with full details came back in four seconds. That architecture is also why the price can be $2 per 1,000 jobs: a browser-based scraper burns roughly five times the compute for the same result, and the buyer pays for it in the end.

It exports past the 1,000-result ceiling

The search API caps any single query at 1,000 reachable hits, which is the wall every WTTJ scraper hits, and the reason most of them quietly return 1,000 rows and call it a day. This one counts the matches first, and when the count exceeds the cap it splits the query recursively on the publication timestamp until every segment fits under it, then walks the segments newest first. maxItems: 0 therefore means every matching job, verified on exports of 3,693 and 9,064 jobs, and the full 88,902-listing corpus is reachable the same way.

Direct ATS apply URL

When the employer routes applications to their own system, applyUrl is that system's URL and ats is external or kombo. In a 300-listing sample taken on 5 September 2026, 213 carried one, landing on SmartRecruiters, Greenhouse, Workday, Talentsoft, Aplitrak, Njoyn and a long tail of French ATS vendors. That single field is what turns a scraped listing into something actionable: it identifies the employer's recruiting stack for ATS-integration sales, and it lets an aggregator send candidates to the source rather than to an intermediate page.

Fifteen filters, applied before collection

Country, city, GPS radius, contract type, remote policy, listing language, maximum experience, education level, minimum yearly salary, company sector, profession category, company size range, publication window, company list, title-only search. All of them are translated into search-API filters and applied server-side, so a narrow query is faster and costs less, rather than fetching everything and throwing most of it away.

It keeps working when the key rotates

The public search key is read from the live Welcome to the Jungle runtime config at the start of every run, with a bundled fallback if that request fails. Key rotations do not break scheduled runs. The search itself is tried across four API hosts in turn, so a single host having a bad day does not fail the run.

It respects your spend cap and fails honestly

Charging happens as each job is written, through the mechanism that enforces the per-run maxTotalChargeUsd limit you set. When the cap is reached the run stops cleanly and says so in the log and the status message. And when something genuinely breaks, an invalid GPS point for instance, the run is marked FAILED rather than reported as a successful empty run.


Pricing

Pay-per-event, no monthly fee, no compute-unit surprise on top.

EventPriceWhen it fires
job-scraped$0.002Once per job written to the dataset, so $2 per 1,000 jobs
apify-default-dataset-item$0.00001Once per dataset item
apify-actor-start$0.00005Once per run, per GB of memory allocated

Worked examples, at 1 GB of memory:

  • 100 jobs, the default run: 100 × $0.00201 + $0.00005 = $0.20
  • 1,000 jobs: $2.01
  • 5,000 jobs: $10.05
  • Every French listing, 70,853 jobs on 5 September 2026: $142.42
  • The entire corpus, 88,902 jobs: $178.69

Two things that are not obvious and are worth stating plainly. Full job details cost exactly the same as titles only, because you are billed per job, not per request, so there is no reason to run with includeDetails: false unless you want speed. And filtering is free: the filters are applied by the search API before collection, so narrowing a search cuts the bill proportionally.


Limits, and what this scraper does not do

It does not collect personal data. No candidate profiles, no recruiter names, no applicant information. Only public job listings and the public company profile attached to them.

applyUrl is null when the employer uses Welcome to the Jungle's own application kit, which the ats field reports as wkit. There is no external URL to return in that case, because the application genuinely happens on Welcome to the Jungle. Use url as the fallback link.

description, skills, tools, applyUrl, companyWebsite, companyLinkedin and the rest of the detail block only exist when includeDetails is true. With the option off, those keys are absent or null.

Salary is published on a minority of listings: 29,488 of 88,902 on 5 September 2026. Setting salaryYearlyMin excludes every listing without a figure, which is the right call for compensation research and the wrong one for exhaustive collection.

Descriptions, candidate profiles and recruitment processes come back as HTML, the way the employer wrote them in the editor. Strip the tags yourself if your pipeline wants plain text.

Localized labels follow resultsLanguage, but the job text is never translated. A French listing stays in French whatever you set, and companyIndustry comes back in English regardless.

There is no cross-run deduplication yet. Results are deduplicated within a run, on the job UUID; if you run daily, keep your own register of seen id values, or merge into a named dataset.

publishedAt is refreshed when an employer renews a listing, so it is not a reliable first-publication date. Use it as a recency signal, not as an archive timestamp.

The cities filter is an exact match on the name as Welcome to the Jungle writes it, so a typo returns nothing rather than an approximation. For anything that looks like a labour market rather than a single town, aroundLatLng with a radius is the better tool.

A very large export with details takes real time, roughly ten jobs per second in steady state once the detail API starts rate-limiting, so plan around 600 jobs per minute and raise the run timeout accordingly. The Actor logs a warning with an estimate when a run is going to be long.

Company slugs that currently have no open job return nothing. That is not a bug, it is a company with no active listings.

This Actor scrapes jobs. It does not scrape Welcome to the Jungle company pages on their own, employee reviews, ratings, media articles, or the video content on company profiles.


FAQ

Can I scrape Welcome to the Jungle without an account? Yes. The Actor uses public endpoints and never logs in. You need an Apify account to run it, not a Welcome to the Jungle one.

Is scraping Welcome to the Jungle legal? The Actor collects publicly available job listings through the same public APIs the website itself calls. It accesses no personal data, does not authenticate, and bypasses no access control. Job listings are information employers pay to have distributed. That said, legality depends on what you do with the data, so check the site's terms of service and the rules that apply to your use case and jurisdiction, particularly if you republish content.

How do I get the direct apply URL for a WTTJ job? Leave includeDetails on, which is the default, and read applyUrl. When it is null, check ats: a value of wkit means the employer receives applications on Welcome to the Jungle itself and there is no external URL.

How many Welcome to the Jungle job listings are there? 88,902 on 5 September 2026, of which 70,853 in France. The number moves daily. Set maxItems: 0 with no filters and the Actor exports all of them.

Can I export more than 1,000 WTTJ jobs? Yes, that is one of the reasons this Actor exists. The search API caps a single query at 1,000 hits; the Actor splits the export by publication date until every slice fits under the cap. Exports of 3,693 and 9,064 jobs are verified, and the full corpus is reachable.

How do I export WTTJ jobs to CSV or Excel? From the console, open the dataset after the run and pick CSV, Excel, JSON, XML or RSS. From the API, add format=csv or format=xlsx to the dataset items call. The cities field exists precisely so that spreadsheets get a readable location column without unpacking the offices array.

Does it cover jobs outside France? Yes. The corpus is shared across all Welcome to the Jungle regional sites, and the country filter works everywhere: 16,677 listings in the United States, 4,750 in the United Kingdom, 1,877 in Canada, plus Spain, Germany, Belgium, Switzerland, Italy and the Czech Republic. resultsLanguage only changes the language of labels, not which jobs you see.

How fresh is the data? The Actor queries the live search index the website itself uses, so results reflect the site at the moment of the run. Around 2,700 listings enter or are renewed in the corpus every 24 hours.

Can I run the Welcome to the Jungle scraper on a schedule? Yes, with Apify Schedules. The usual setup is a daily run with publishedWithinDays: "1" and sortBy: "newest". Handle deduplication downstream on the id field, since Welcome to the Jungle refreshes publication dates on renewal.

Does it return salary data? When the employer published it, which is roughly a third of listings. You get the raw range, the currency, the period, a ready-to-display string, and the yearly-normalized minimum that makes daily rates comparable with annual packages.

Can I get all the jobs of one company? Put the company slug from its Welcome to the Jungle URL, or its exact name, into companySlugs. Multiple companies in one run is fine, and the other filters are ignored for them.

Do I need a proxy? No. The search API needs none and detail requests work from Apify's datacenter IPs, with automatic retries when one is rate-limited. If a very large run logs repeated detail failures, set a residential proxy in the Advanced section as a fallback.

A filter I need is missing, or something looks wrong. What do I do? Open an Issue on the Actor page with the input you ran. Filters that exist in the underlying search index are usually quick to add.


Integrations

The dataset is a standard Apify dataset, so everything the platform offers applies to it. Export as JSON, JSONL, CSV, Excel, XML or RSS, from the console or by adding format= to the API call. Point a webhook at your own endpoint so a finished run pushes straight into your pipeline instead of you polling for it. Connect Zapier, Make, n8n, Google Sheets, Slack or Airtable through the Apify integrations, or write to Google Drive and Amazon S3 from the run.

For agents, Apify exposes its Actors through its MCP server, so an assistant that speaks MCP can call this scraper as a tool and read the results back without any glue code of yours. The input schema is descriptive enough for a model to fill in on its own, which is the point of every field having a description that says what happens when you leave it empty.


Built and maintained by Alex Morain. Bug reports and filter requests go in the Issues tab of the Actor page and get looked at.