# Welcome to the Jungle Jobs Scraper (`steadyscrape/welcome-to-the-jungle-jobs-scraper`) Actor

Scrape job ads from Welcome to the Jungle (France, UK, US, Europe): structured salary, contract, remote policy, full description, skills, tools, benefits, hiring process and company data. Filter by country, city, company and date. Goes past the 1,000-job search limit. No login.

- **URL**: https://apify.com/steadyscrape/welcome-to-the-jungle-jobs-scraper.md
- **Developed by:** [Steady Scrape](https://apify.com/steadyscrape) (community)
- **Categories:** Jobs, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$2.00 / 1,000 jobs

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/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### What does Welcome to the Jungle Jobs Scraper do?

It collects job ads from [Welcome to the Jungle](https://www.welcometothejungle.com), the leading tech and startup job board of France, with a growing catalogue in the UK, the US and the rest of Europe: about 90,000 live jobs. For every job you get the title, company, **structured salary** (minimum, maximum, currency, period), contract type, remote policy, offices, profession, required experience and education, summary, key missions, candidate profile, benefits, the full description, hiring process, skills, tools, start date, office address and the link to apply, plus company data (size, creation year, labels, gender-equality index).

It reads the same public data the site shows to any visitor: no login, no cookies, no browser. A run of 100 jobs with full details takes about half a minute.

### Why use it?

- **Job aggregators and niche job boards**: feed fresh ads by keyword, country, city and profession, on a schedule.
- **Recruiters and staffing agencies**: see which companies are hiring for which roles, with salary bands and the tools they use.
- **Sales and lead generation**: a company that is hiring is a company that is buying. Find startups growing a team in your niche, with their size, sector and tech stack.
- **Salary and labour-market research**: salaries arrive as numbers, not free text, so they can be averaged and compared at once.
- **AI agents and job-matching tools**: clean, structured job descriptions, skills and tools ready for an LLM.

### Features

- **Goes past the 1,000-job limit**: the site lists at most 1,000 jobs per search. With *Full coverage* on, a larger search is split by country, contract type, profession, region and company until every part fits, and every job is stored once. The run summary tells exactly how many jobs the site holds for each search and how many were stored.
- **Track specific companies**: paste company profile links to get only their openings.
- **Several searches per run**: one line per keyword. A job found by two searches is stored, and charged, once.
- **Filters**: countries, cities, companies, contract type (permanent, fixed-term, freelance, internship, apprenticeship, VIE…), remote policy, 20 professions, and *posted within N days* for any N.
- **Labels in 5 languages**: English, French, Spanish, Czech, Slovak.
- **Honest billing**: you pay per job stored. Failed searches and duplicates cost nothing, and the run stops at your maximum cost.
- **Built to last**: the Actor reads the site's public search credentials at the start of every run, so it keeps working when the site rotates them.

### How to scrape Welcome to the Jungle jobs

1. Add one or more **keywords** (job title, skill or technology), or leave them empty to get every job matching the filters.
2. Optionally set **countries** (`FR`, `GB`, `US`…), **cities**, **companies**, **contract types**, **remote work**, **categories**, **posted within** and the **maximum jobs per search**.
3. Click **Start**. Download the jobs as JSON, CSV, Excel or HTML, or read them through the API.

To collect only new jobs, schedule the Actor daily with *Posted within: 1* and *Sort by: Newest first*.

### Input example

```json
{
    "keywords": ["data engineer", "analytics engineer"],
    "countries": ["FR"],
    "cities": ["Paris", "Lyon"],
    "contractTypes": ["fullTime", "freelance"],
    "remote": ["fullyRemote", "partial"],
    "postedWithinDays": 7,
    "maxJobsPerSearch": 200,
    "includeDetails": true
}
```

### Output example

One item per job (long texts shortened here):

```json
{
    "jobId": "666bc585-2f13-474d-b7e4-5bb2fac42425",
    "slug": "data-engineer-spark_lyon_SI_rqLxD5r",
    "title": "Data Engineer (Spark)",
    "companyName": "Shape It",
    "company": {
        "name": "Shape It",
        "slug": "shape-it",
        "url": "https://www.welcometothejungle.com/en/companies/shape-it",
        "summary": "ESN verte et sociale avec engagement RSE et excellence technique.",
        "logoUrl": "https://cdn-images.welcometothejungle.com/…",
        "employees": 105,
        "creationYear": 2020,
        "labels": ["charte-de-la-diversite", "ecovadis-silver", "mission-company", "rfar"],
        "equalityIndex": 94
    },
    "contractType": "full_time",
    "contractDurationMinMonths": null,
    "contractDurationMaxMonths": null,
    "remote": "partial",
    "location": "Lyon, France",
    "offices": [{ "city": "Lyon", "state": "Auvergne-Rhone-Alpes", "country": "France", "countryCode": "FR" }],
    "salaryMin": 43000,
    "salaryMax": 50000,
    "salaryCurrency": "EUR",
    "salaryPeriod": "yearly",
    "salaryYearlyMin": 43000,
    "experienceYearsMin": 4,
    "educationLevel": "bac_5",
    "category": "Tech & Engineering",
    "subCategory": "Data / Business Intelligence",
    "profession": "Data Engineer",
    "sectors": ["Software", "IT / Digital", "Big Data"],
    "language": "fr",
    "publishedAt": "2026-09-16T10:17:56.000Z",
    "summary": "Rejoins une équipe engagée dans un projet client stimulant…",
    "keyMissions": [
        "Apporter une expertise en Big Data (Spark) pour faciliter la manipulation des données.",
        "Mettre en place des solutions de stockage de données (SQL, NoSQL, etc.) et veiller à la sécurisation des pipelines de données."
    ],
    "candidateProfile": "**Profil recherché**\n\nTu es notre personne idéale si tu maîtrises…",
    "benefits": ["Game room", "Diversity manifesto", "Reduction of working time (RTT)", "Cooptation bonus"],
    "isBoosted": false,
    "url": "https://www.welcometothejungle.com/en/companies/shape-it/jobs/data-engineer-spark_lyon_SI_rqLxD5r",
    "searchKeywords": "data engineer",
    "description": "Rejoindre une équipe de shapers qui partagent des valeurs et des convictions écologiques…",
    "descriptionHtml": "<p>Rejoindre une équipe de shapers…",
    "recruitmentProcess": "Si nous sommes conquis par ton profil et ta personnalité, voici ce qu’il t’attend :…",
    "skills": ["Programming languages"],
    "tools": ["Java", "Oracle", "NoSQL", "Scala", "SQL", "Python"],
    "applyUrl": null,
    "startDate": null,
    "updatedAt": "2026-09-16T10:17:59.677Z",
    "address": "53 Rue du Président Édouard Herriot, 69002 Lyon, France",
    "scrapedAt": "2026-09-17T16:05:42.495Z"
}
```

#### Output fields

| Field | Description |
|---|---|
| `jobId`, `slug`, `url` | The site's job reference, its address inside the company, and the link to the ad |
| `title`, `companyName` | Job title and hiring company |
| `company` | Name, profile link, one-line summary, logo, number of employees, creation year, labels (B Corp, Great Place to Work…) and France's gender-equality index (0–100) |
| `contractType` | `full_time`, `part_time`, `temporary`, `freelance`, `internship`, `apprenticeship`, `graduate_program`, `vie`, `volunteer`, `other` |
| `contractDurationMinMonths`, `contractDurationMaxMonths` | For fixed-term contracts and internships |
| `remote` | `fulltime`, `partial` (a few days a week), `punctual` (occasional), `no`, or `unknown` |
| `location`, `offices` | First office as "City, Country", and every office with city, state, country and ISO code |
| `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod` | The published salary as numbers; `null` when the company does not publish it (about two thirds of the ads) |
| `salaryYearlyMin` | The minimum converted to a yearly amount by the site, to compare jobs paid monthly, daily or yearly |
| `experienceYearsMin`, `educationLevel` | Minimum years of experience; education as the site codes it (`bac_5` = master's degree) |
| `category`, `subCategory`, `profession` | The site's profession tree, e.g. Tech & Engineering / Data / Data Engineer |
| `sectors` | The company's sectors |
| `language` | Language the ad is written in |
| `publishedAt` | ISO 8601 UTC |
| `summary`, `keyMissions`, `candidateProfile`, `benefits` | The ad's pitch, main tasks, wanted profile and perks |
| `isBoosted` | The ad is a paid, promoted listing |
| `searchKeywords` | Which of your keywords found the job first |
| `description`, `descriptionHtml` | Full job description as readable text and as the original HTML |
| `recruitmentProcess` | The hiring steps, when the company describes them |
| `skills`, `tools` | Soft and hard skills, and the tools or technologies of the job |
| `applyUrl` | The employer's own application page; `null` when candidates apply on Welcome to the Jungle |
| `startDate`, `updatedAt` | Expected start and last update, ISO 8601 UTC |
| `address` | Street address of the office |
| `scrapedAt` | When the job was read, ISO 8601 UTC |

With **Include job details** off, the fields from `description` to `address` are `null`.

### How much does it cost?

You pay **per job stored**: US$2 per 1,000 jobs, with or without details, and nothing else. Platform usage is included. Duplicates, failed searches and jobs beyond your maximum cost are not charged. Apify's free plan is enough to try it.

### Limitations

- The site lists 1,000 jobs per search. Turn on **Full coverage** to go past it. A search still too large after being split by country, contract type, profession, region and company is reported as truncated in `SUMMARY`, with the exact number of jobs the site holds.
- Cities must be written as the site shows them (`Paris`, not `paris 9e`). A city the site does not know simply returns no jobs.
- Ads stay in the language they were written in (mostly French and English); only labels are translated.
- A job that lists no office is not reachable through the country split of *Full coverage*.

### Is it legal?

This Actor only reads job ads that the site publishes for any visitor, without logging in, at a gentle pace. Job ads are business information, but some descriptions include a recruiter's name: handle those under the privacy laws that apply to you (GDPR). Check the terms that apply to your use of the data, and consult a lawyer if unsure. Read more in Apify's blog post on [the legality of web scraping](https://blog.apify.com/is-web-scraping-legal/).

### Feedback

Need a field or a filter that isn't here? Open an issue in the **Issues** tab — they are answered quickly.

# Actor input Schema

## `keywords` (type: `array`):

Job titles, skills or technologies. Each line is its own search; a job found by several searches is stored and charged once. Leave empty to get every job matching the filters below.

## `countries` (type: `array`):

Two-letter country codes of the job's office, e.g. <code>FR</code>, <code>GB</code>, <code>US</code>, <code>DE</code>, <code>ES</code>, <code>BE</code>, <code>NL</code>, <code>CZ</code>. Leave empty for every country (the site lists jobs in over 200).

## `cities` (type: `array`):

City names exactly as the site shows them, e.g. <code>Paris</code>, <code>London</code>, <code>Lyon</code>, <code>New York</code>.

## `companies` (type: `array`):

Only jobs of these companies: paste their Welcome to the Jungle profile link (<code>https://www.welcometothejungle.com/en/companies/doctolib</code>) or the last part of it (<code>doctolib</code>).

## `maxJobsPerSearch` (type: `integer`):

Stop each search after this many jobs. 0 means all of them. The site lists 1,000 jobs per search; turn on "Full coverage" to go past that.

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

Only jobs published in the last N days. 0 means any time. Combine with a daily schedule to collect new jobs only.

## `sortBy` (type: `string`):

The order in which the site lists the jobs, which decides which ones you get when you set a maximum.

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

Leave empty for all.

## `remote` (type: `array`):

Leave empty for all, including jobs that do not say.

## `categories` (type: `array`):

Only jobs of these professions. Leave empty for all.

## `language` (type: `string`):

The language of category, sector, benefit and skill names, and of the job links. Job ads themselves stay in the language they were written in.

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

Open each job page for the full description, the hiring process, skills, tools, start date, office address and the link to apply. One extra request per job; turn off for a faster run with the search-result fields only (which already include the summary, key missions, candidate profile, salary and benefits). The price per job is the same.

## `fullCoverage` (type: `boolean`):

The site lists at most 1,000 jobs per search. When a search holds more, repeat it split by country, contract type, profession, region and company until every part fits. Each job is still stored and charged once.

## Actor input object example

```json
{
  "keywords": [
    "data engineer"
  ],
  "maxJobsPerSearch": 50,
  "postedWithinDays": 0,
  "sortBy": "relevance",
  "contractTypes": [],
  "remote": [],
  "categories": [],
  "language": "en",
  "includeDetails": true,
  "fullCoverage": false
}
```

# Actor output Schema

## `jobs` (type: `string`):

No description

## `summary` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

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

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "keywords": [
        "data engineer"
    ],
    "maxJobsPerSearch": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("steadyscrape/welcome-to-the-jungle-jobs-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "keywords": ["data engineer"],
    "maxJobsPerSearch": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("steadyscrape/welcome-to-the-jungle-jobs-scraper").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "keywords": [
    "data engineer"
  ],
  "maxJobsPerSearch": 50
}' |
apify call steadyscrape/welcome-to-the-jungle-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,steadyscrape/welcome-to-the-jungle-jobs-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/NEITXC2Gv21IL38rK/builds/CkAQXx1qMx9NkMAVQ/openapi.json
