# Welcome to the Jungle Scraper: Jobs from welcometothejungle.com (`hexagone-data/wttj-scraper`) Actor

Scrape Welcome to the Jungle company job pages, SEO job pages and job ads: title, company, locations, contract, remote, salary, date, missions, benefits; optional full description, profile, skills, tools and apply link. Searches over 1,000 jobs are split. Pay per result.

- **URL**: https://apify.com/hexagone-data/wttj-scraper.md
- **Developed by:** [Hexagone Data](https://apify.com/hexagone-data) (community)
- **Categories:** Jobs, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.35 / 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## Welcome to the Jungle Jobs Scraper

Get job offers from [welcometothejungle.com](https://www.welcometothejungle.com) as clean, typed records: title,
company, locations, contract, remote policy, salary with its period and currency, publication date, missions,
benefits, and optionally the full job page (description, profile, skills, tools, address, apply link, status).

It replays the request the website's own company and SEO pages send to their public job index (same index, same
filters, same page size), so the records follow the jobs and the order of the page you pasted. Searches with more than the 1,000 results the
site serves per query are split automatically, and the run summary tells you, per URL, how many jobs the site
announced and how many you got.

### Try it with 20 jobs

1. Keep the prefilled start URL (`https://www.welcometothejungle.com/fr/companies/sii/jobs`) and
   **Maximum number of jobs = 20**.
2. Click **Start**. The run takes a few seconds and costs $0.015 (or $0.035 with job details), start fee included.
3. Open the **Jobs** tab, then **Run summary** to see what was announced and what was collected.

### What to paste

| You paste | Example | What you get |
|---|---|---|
| A company jobs page, with the filters you clicked on the site | `https://www.welcometothejungle.com/fr/companies/thales/jobs?refinementList%5Bcontract_type%5D%5B%5D=internship` | Every job of that page, all pages (30 per page), filters kept exactly |
| An SEO jobs page | `https://www.welcometothejungle.com/fr/pages/emploi-paris-75000` | The jobs that page lists (20 per page), all pages |
| A single job page | `https://www.welcometothejungle.com/fr/companies/sii/jobs/developpeur-java-confirme-f-h_toulouse_GS_mrpQZbV` | That job, with its details; a job that is no longer open comes with `status: "archived"` |
| `/en/` pages | `https://www.welcometothejungle.com/en/companies/mistral-ai/jobs` | Same jobs, English labels and URLs |

- **Group pages.** Some company pages list the jobs of a whole group: `/fr/companies/edf/jobs` shows the jobs of EDF and
  9 subsidiaries (Framatome, EDF Renouvelables…), 58 apprenticeships where "edf" alone has 51. The Actor reads which
  companies the page lists from the site's own page configuration (one small request per company page, cached for the
  run) and filters exactly like the page, so you get the same jobs, the same total and the same page/position. If that
  configuration cannot be read, it filters on the company of the URL alone, warns you (`COMPANY_FILTER_FALLBACK`) and
  marks the URL `partial_collection` ("company filter could not be read: subsidiaries of a group may be missing"),
  never `done`: the total it compares to is then the company's own, not the page's. A temporary error is retried once
  when the run resumes after a migration.
- **Company page that does not exist.** Some companies have jobs on the site but no jobs page (e.g.
  `/en/companies/l-oreal/jobs` answers "Error 404"). Their jobs are still in the site's index and their job pages are
  public: the Actor delivers them, filtered on the company of the URL, with the warning `COMPANY_JOBS_PAGE_NOT_FOUND`.
- `page=` in a pasted URL is ignored: collection always starts at page 1.
- **Keyword search is not public on the site any more.** Since October 2026 the site shows keyword search results
  only to logged-in users (`/fr/jobs?query=...` displays a sign-up page). Old keyword URLs are still accepted and
  translated to the job index, with a clear warning; the **keyword** field does the same. Because there is no public
  page to compare with, we do not promise "same as the website search" for those.
- Keyword mode filters: `countryCode` (FR by default, empty = all), `contractTypes`, `remote`, `city`, `language`
  (`fr`/`en` labels and URLs), `postedSince` (YYYY-MM-DD).

### Output

One record per job and run (duplicates across start URLs are delivered once). Unknown values are `null`: never an
empty string, an invented `0`, `false` or "no". A real record (texts shortened with "…"):

```json
{
 "jobId": "4a986e90-1737-4247-a41e-f6820e8d6e81",
 "jobReference": "GS_A649137",
 "url": "https://www.welcometothejungle.com/fr/companies/sii/jobs/ingenieur-ivv-logiciel-embarque-aeronautique-f-h_toulouse_GS_A649137",
 "title": "Ingénieur(e) IVV Logiciel Embarqué Aéronautique (F/H)",
 "company": "Groupe SII", "companyId": "5p9XmWL", "companySlug": "sii",
 "companyUrl": "https://www.welcometothejungle.com/fr/companies/sii",
 "companyLogo": "https://cdn-images.welcometothejungle.com/-OCGJ1AoQbY-MO_H0BCX9Dq_3njRpPrSEcpoBgJmud8/rs:a…",
 "companySize": 16000,
 "location": "Toulouse", "locations": ["Toulouse"],
 "offices": [{"city": "Toulouse", "localCity": "Toulouse", "district": "Haute-Garonne", "state": "Occitanie", "country": "France", "countryCode": "FR"}],
 "contractType": "full_time", "contractTypeLabel": "CDI",
 "contractDurationMin": null, "contractDurationMax": null,
 "remote": "no", "remoteLabel": "Télétravail non autorisé",
 "salaryMin": 35000, "salaryMax": 60000, "salaryPeriod": "year", "salaryCurrency": "EUR",
 "experienceLevelMin": null, "educationLevel": null,
 "postedAt": "2026-10-28T23:03:24Z",
 "summary": "Rejoignez SII, un leader mondial de l'industrie aéronautique. En tant qu'Ingénieur Vérific…",
 "keyMissions": ["Développement de scripts de test et mise en œuvre des cas de test auto…", "…"],
 "benefits": ["Horaires de travail flexibles", "Entre 1-2 jours de télétravail", "…"],
 "sectors": ["Logiciels", "Intelligence artificielle / Machine Learning", "IT / Digital"],
 "language": "fr", "isBoosted": false,
 "sourceUrl": "https://www.welcometothejungle.com/fr/companies/sii/jobs",
 "page": 2, "position": 6, "searchPart": null,
 "scrapedAt": "2026-10-29T12:06:50+00:00",
 "detailsSource": "jobPage",
 "descriptionHtml": "<p>Dans le cadre d&#39;une mission stratégique pour un leader mondial de l&#39;industrie a…",
 "descriptionText": "Dans le cadre d'une mission stratégique pour un leader mondial de l'industrie aéronautique…",
 "profileHtml": "<p>Compétences requises :</p><p>C, Doors, Jira, Python</p><p>Qualités désirées :</p><p>For…",
 "profileText": "Compétences requises :\n\nC, Doors, Jira, Python\n\nQualités désirées :\n\nForce de proposition,…",
 "recruitmentProcess": null,
 "applyUrl": "https://sii-group.com/fr-FR/offers/ingenieure-ivv-logiciel-embarque-aeronautique-fh?source…",
 "skills": ["Communication", "Gestion de la conformité"], "tools": ["Linux", "Python", "JIRA"],
 "startDate": null, "address": "Toulouse, Occitanie, France", "zipCode": "31000",
 "latitude": 43.60579, "longitude": 1.44863,
 "profession": "Ingénierie matérielle", "professionCategory": "Technologie et ingénierie",
 "updatedAt": "2026-10-28T23:03:24.635880Z", "status": "published",
 "jobPageSalaryMin": 35000, "jobPageSalaryMax": 60000, "jobPageSalaryPeriod": "year", "jobPageSalaryCurrency": "EUR"
}
```

Good to know:

- `remote` keeps the site's code: `no`, `partial`, `punctual`, `fulltime`, or **`unknown`** (about 45% of the index:
  the card shows no remote label). `unknown` is never turned into "no"; its `remoteLabel` is `null`.
- Salary: `salaryMin` alone means "from" (the card shows "≥ 55K €"), `salaryMax` alone means "under" ("< 300 € par
  jour"); `salaryPeriod` is `year`, `month` or `day`. When the site stores a period without any amount, all four
  salary fields are `null` (nothing is displayed). Amounts are numbers (`45000`, not `45000.0` or "45K"). An amount
  of 0 in the index is delivered as `null` (the card shows no salary and the job page says "Non spécifié").
- **Two salary sources, kept apart.** `salaryMin`/`salaryMax`/`salaryPeriod`/`salaryCurrency` come from the search
  index, exactly what the job card shows. With includeDetails, `jobPageSalaryMin`/`jobPageSalaryMax`/
  `jobPageSalaryPeriod`/`jobPageSalaryCurrency` hold the salary shown on the job page itself. They usually agree,
  but the site does not always: one job had no salary on its card and "35K à 40K €" on its page. Use the job page
  values when you want the most complete salary, the index values when you want what the listing shows.
- `locations` uses the local city name the card shows ("Genève", not "Geneva") in the card's order; `location` is the
  full list joined by ", " even when the card truncates it ("… +18").
- `language` is the language of the job ad (`fr`, `en`, `es`…), not the language of the page you pasted.
- `jobId` is the site's UUID; `jobReference` (the short code at the end of most job URLs) is `null` for about 16% of jobs.
- `contractTypeLabel` / `remoteLabel` are the labels displayed in the language of your URL; a code whose label was
  not measured gets `null` (the code is still delivered).
- `searchPart` is `null` for jobs read from the site's own pages; for jobs found by splitting a search over 1,000
  results, it holds the extra filter of that part (e.g. `contract_type:internship`).
- Detail fields (`descriptionHtml` … `status`) are filled only with **includeDetails** (or for a pasted job page);
  otherwise they are `null` and `detailsSource` is `listing`.

### Run summary

Each run writes a readable **Run summary** (key-value store record `SUMMARY`) and the same data as JSON (`OUTPUT`):
per start URL, its status, the jobs delivered, the jobs the site announced (`jobsAnnouncedBySite`), the distinct jobs
seen (`jobsSeen`), what is missing and why.

| Status | Meaning |
|---|---|
| `done` | Every announced job was seen and delivered |
| `no_new_jobs` | Every job of this URL was already delivered by an earlier start URL |
| `stopped_at_limit` | Your `maxItems` or maximum charge was reached |
| `partial_collection` | Fewer distinct jobs than announced, with the reason (page that failed, empty page, page that only repeated jobs, page count that dropped, split part that failed). Never reported as `done` |
| `no_results` | The site announced 0 jobs: the search is empty, the URL is wrong or the site is down (warning `NO_RESULTS`). A run where every URL is empty fails |
| `job_not_available` | A pasted job URL served the site's "page not found" (sent with HTTP 200) or another job; nothing delivered or charged |
| `blocked_by_site`, `http_error`, `network_error`, `unrecognized_page` | The site refused or failed; this is never reported as an empty search |

Warnings you may see: `ANO_COUVERTURE` (partial collection, with the numbers), `SEARCH_URL_NOT_PUBLIC`,
`COMPANY_JOBS_PAGE_NOT_FOUND`, `COMPANY_FILTER_FALLBACK`,
`JOB_ARCHIVED`, `ANO_DETAILS` / `DETAILS_STOPPED` (job pages not read), `UNEXPECTED_DATA` / `UNKNOWN_VALUE` (one odd
value: the job is delivered without that field, the run continues), `KEY_FALLBACK`, `PROXY_SETTING`.
The final status message never says everything went fine when one of these counters is not zero.
When a job page answers something other than a normal page (for example an HTTP 202 anti-bot challenge), the first
3 such answers are saved in the key-value store record `DEBUG_PAGES` (status, response headers, first 3,000
characters, final URL, proxy session number; no password or key) so the cause can be checked.

### Pricing

Pay per result, no subscription:

- **$0.0005 per job** delivered (`apify-default-dataset-item`);
- **+ $0.001 per job whose page was read** for details (`job-details`, only with includeDetails or a pasted job page);
- **+ $0.005 per run** to start (`apify-actor-start`, once per GB of memory; the default is 1 GB).

Apify subscribers pay less automatically on jobs and on the run start: 10% off on the Bronze plan, 20% on Silver, 30% on Gold and above. The job-details charge has no discount: $0.001 per job page on every plan.

| | 20 jobs | 1,000 jobs |
|---|---|---|
| Without details | $0.015 | $0.505 |
| With details | $0.035 | $1.505 |

These totals include the $0.005 start fee.

The job-details price includes the residential proxy traffic that job pages need (about 85-92 KB transferred per
page, measured). A job whose page could not be read is never charged the details event. Your maximum charge per run
is respected: the run stops cleanly before reading a job page it could not pay for (a pasted job page is only read
when the job and its details both fit in your maximum charge).

### Known limits

- Keyword search is no longer public on the site (see "What to paste"); keyword results come from the same index
  but cannot be compared with a public page.
- The site serves at most 1,000 results per query. Larger searches are split by contract type, remote policy, then
  publication date; jobs published or removed while the run splits a large search can make the count differ, and the
  summary says so (`partial_collection`, never `done`).
- Filters other than `refinementList[...]` and `query` in a pasted URL (for example a sort) are not applied; the
  summary lists them (`IGNORED_URL_PARAMETERS`).
- The site's company page counter includes a "Candidature spontanée" card (e.g. 479 for 478 jobs); it is not a job
  and is neither counted nor delivered.
- A job that is no longer open is not in the index: it is only reachable as a pasted job page, delivered with
  `status: "archived"` and the fields its page gives (sectors, size, logo and boost stay `null`). For such a job the
  salary fields come from its job page, the only source left (they then equal `jobPageSalary*`); for every other job
  `salary*` is the index value the card shows.
- **Bot challenge on some job pages.** On Apify, about 5% of job pages answer with an anti-bot challenge (HTTP 202
  from CloudFront, `x-amzn-waf-action: challenge`, AWS WAF) instead of the page, even after new IPs. A browser solves
  it, an HTTP client cannot. Those jobs are delivered without details and without the `job-details` charge; the run
  summary counts them, and the first answers are kept in `DEBUG_PAGES`.
- **The job page needs residential proxy.** The search index works from datacenter IPs, but the site refuses job
  pages from datacenter IPs (HTTP 403, measured 2026-10-29). Job pages and SEO pages therefore use their own setting,
  **Proxy for job pages** (`detailsProxyConfiguration`, Apify RESIDENTIAL, country FR, by default); a refused page is
  retried with a new IP, up to 5 times. **Proxy for the search index** (`proxyConfiguration`) only applies to the index.
  If you set the job pages proxy without the RESIDENTIAL group, or turn it off, the run does as you ask and warns you
  (`PROXY_SETTING`): details will likely fail.
- **Run time (measured on Apify).** Without details, the index is fast: 7,139 jobs ("developpeur", France) in about
  1 minute. With details, count about 1 second per job (one job page each, about 288 KB uncompressed and 85-92 KB
  transferred): 16-20 minutes per 1,000 jobs. The default run timeout is 4 hours (about 14,000 jobs with details); for
  a larger collection with details, raise the timeout in the run options, otherwise the run stops before writing its
  summary.

### Support

Found a job the site shows that the run missed, or a field that differs from the page? Open an issue on the Actor's
**Issues** tab with the start URL and the run ID; the run summary usually points to the cause.

This Actor is not affiliated with, endorsed or sponsored by Welcome to the Jungle. "Welcome to the Jungle" is a
trademark of its owner. It reads publicly available job offers only; use the data in line with the site's terms and
the law that applies to you (GDPR for personal data).

### En français

Collez une page entreprise de welcometothejungle.com avec les filtres choisis sur le site (stage, alternance,
télétravail…), une page SEO (`/fr/pages/emploi-paris-75000`) ou une fiche d'offre : vous obtenez une ligne par offre
(titre, entreprise, lieux, contrat, télétravail, salaire avec sa période, date, missions, avantages ; avec les
détails : description, profil, compétences, outils, adresse, lien de candidature, statut). La recherche par mot-clé
n'est plus visible sans compte sur le site : elle reste possible ici, avec un avertissement. Au-delà de 1 000
résultats, la recherche est découpée automatiquement ; le résumé du run dit, URL par URL, combien d'offres le site
annonçait et combien ont été livrées. Prix : 0,50 $ les 1 000 offres, 1,50 $ avec les détails, plus 0,005 $ de démarrage par run ; remise automatique pour les abonnés Apify sur les offres et le démarrage (−10 % Bronze, −20 % Silver, −30 % Gold et plus) ; pas de remise sur les détails (0,001 $ par fiche quel que soit l'abonnement).

# Actor input Schema

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

welcometothejungle.com pages: company job pages with your filters as the site built them (e.g. https://www.welcometothejungle.com/fr/companies/thales/jobs?refinementList%5Bcontract_type%5D%5B%5D=internship), SEO jobs pages (/fr/pages/emploi-paris-75000) or single job pages (/fr/companies/<company>/jobs/<job>). Old keyword search URLs (/fr/jobs?query=...) are accepted with a warning: the site no longer shows keyword search without an account. When set, keyword and its filters are ignored.

## `keyword` (type: `string`):

Searches the site's job index for this text (e.g. data analyst). The website itself shows keyword results only to logged-in users, so there is no public page to compare with.

## `countryCode` (type: `string`):

Two-letter office country, FR by default. Leave empty for every country.

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

Any of: full_time, internship, apprenticeship, temporary, freelance, part_time, other, vie, graduate_program, volunteer, idv.

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

Any of: no, partial, punctual, fulltime, unknown.

## `city` (type: `string`):

Office city as written on the site, e.g. Paris, Lyon.

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

Language of the labels and URLs: fr or en. The language of each job ad is in the 'language' field.

## `postedSince` (type: `string`):

Only jobs published after this date, YYYY-MM-DD.

## `maxItems` (type: `integer`):

Stops after this many unique jobs across all start URLs. 0 = no limit. You pay per delivered job.

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

Off by default. When on, each delivered job's page is read once: full description and profile (HTML and text), recruitment process, external apply link, skills, tools, address and coordinates, profession, status. Adds the 'job-details' charge ($0.001 per job whose page was read: $1.50 instead of $0.50 per 1,000 jobs). Job pages need the residential proxy (see 'Proxy for job pages').

## `proxyConfiguration` (type: `object`):

Used for the site's search index API (and /api/env). Apify datacenter proxy by default: enough for the index (measured). Job pages use the next setting.

## `detailsProxyConfiguration` (type: `object`):

Used to read job pages (includeDetails, pasted job pages) and SEO pages. Residential, country FR, by default: the site refuses job pages from datacenter IPs (HTTP 403, measured 2026-10-29). A refused page is retried with a new IP, up to 5 times. Without the RESIDENTIAL group, details will likely fail (the run summary says so).

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.welcometothejungle.com/fr/companies/sii/jobs"
    }
  ],
  "countryCode": "FR",
  "language": "fr",
  "maxItems": 20,
  "includeDetails": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "detailsProxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "FR"
  }
}
```

# Actor output Schema

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

All job records, one per job offer, with every field.

## `jobsOverview` (type: `string`):

Title, company, location, contract, remote, salary, date, link.

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

Readable per-URL summary: status, jobs delivered vs announced, reason for anything missing.

## `summaryJson` (type: `string`):

The same summary as JSON (OUTPUT record).

# 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 = {
    "startUrls": [
        {
            "url": "https://www.welcometothejungle.com/fr/companies/sii/jobs"
        }
    ],
    "maxItems": 20,
    "includeDetails": false,
    "proxyConfiguration": {
        "useApifyProxy": true
    },
    "detailsProxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "FR"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("hexagone-data/wttj-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 = {
    "startUrls": [{ "url": "https://www.welcometothejungle.com/fr/companies/sii/jobs" }],
    "maxItems": 20,
    "includeDetails": False,
    "proxyConfiguration": { "useApifyProxy": True },
    "detailsProxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "FR",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("hexagone-data/wttj-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 '{
  "startUrls": [
    {
      "url": "https://www.welcometothejungle.com/fr/companies/sii/jobs"
    }
  ],
  "maxItems": 20,
  "includeDetails": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "detailsProxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "FR"
  }
}' |
apify call hexagone-data/wttj-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,hexagone-data/wttj-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/yMwHiGbqEnxIdspSJ/builds/7Tfkal3cap566wmR0/openapi.json
