# Facebook Ad Library Scraper (`practicaltools/facebook-ad-library-scraper`) Actor

Scrapes ads from the Facebook Ad Library. Accepts search URLs or Facebook page URLs and returns structured ad data.

- **URL**: https://apify.com/practicaltools/facebook-ad-library-scraper.md
- **Developed by:** [Practical Tools](https://apify.com/practicaltools) (community)
- **Categories:** Social media, Lead generation
- **Features:** Limited permissions
- **Stats:** 128 total users, 19 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.50 / 1,000 ad scrapeds

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

## Facebook Ad Library Scraper

Extract ads from the [Facebook Ad Library](https://www.facebook.com/ads/library/) — creative, landing pages, platforms, impressions, spend, and advertiser page details — without a Facebook account or API key.

Search by **keyword**, pull **every ad an advertiser page is running**, or search for a keyword **inside one advertiser's ads**. Output is one clean row per ad with dates as `YYYY-MM-DD`, ready for CSV, Excel, or JSON.

***

### Quick start

**Search the Ad Library for a keyword**

```json
{ "keyword": "running shoes", "country": "US", "activeStatus": "active", "limitPerSource": 100 }
```

**Get all ads from advertiser pages**

```json
{ "pages": ["https://www.facebook.com/ZapierApp", "nike", "254515547747520"], "limitPerSource": 0 }
```

**Search for a keyword inside an advertiser's ads**

```json
{ "keyword": "free trial", "pages": ["https://www.facebook.com/ZapierApp"], "keywordWithinPages": true }
```

**Monitor a competitor every week** — schedule this and set a run tag per run:

```json
{
    "pages": ["https://www.facebook.com/ZapierApp"],
    "datePreset": "last7d",
    "limitPerSource": 0,
    "includePageSummary": true,
    "runTag": "2026-W39"
}
```

**Political ads about a topic, exact phrase, Instagram only**

```json
{
    "keyword": "climate change",
    "searchType": "keyword_exact_phrase",
    "adType": "political_and_issue_ads",
    "publisherPlatforms": ["instagram"],
    "country": "US",
    "datePreset": "last30d"
}
```

***

### Features

- **No login required** — scrapes the public Ad Library over plain HTTP, no browser
- **Three ways in** — keyword search, advertiser pages, or raw Ad Library URLs
- **Search within an advertiser** — turn on `keywordWithinPages` to find only one advertiser's ads about a topic
- **Advertiser pages in any form** — page URL, handle (`ZapierApp`), numeric page ID, or an Ad Library link
- **Every Ad Library filter** — country, active status, ad category (political, housing, employment, credit), media type, date range, platforms, languages, exact-phrase matching
- **Per-page summary rows** — total ads, active ads, platform breakdown, date range for each advertiser
- **EU transparency** — EU reach with country / age / gender breakdown, targeting, payer and beneficiary, no login needed
- **Rich ad-level fields** — publisher platforms, impressions band, spend and reach (political ads), collation count (number of near-identical variants), page likes and categories, AI-generated flag
- **Clean creatives** — headline, body, CTA, landing page, image, video and thumbnail; carousels nested under `cards`
- **Two output shapes** — one row per ad (default) or one row per creative card
- **Cost control** — per-source and global ad limits
- **Errors in the dataset** — a page that cannot be resolved produces an error row, never a silent empty run
- **Proxy-ready** — optional Apify or custom proxies, usually not needed

***

### Input

#### Sources

| Field | Type | Description |
|-------|------|-------------|
| `keyword` | string | A search of the whole Ad Library for this term, like the Ad Library search box. |
| `pages` | string\[] | Advertiser pages: every ad each one is running. Each entry may be a page URL, a handle, a numeric page ID, or an Ad Library URL containing `view_all_page_id`. |
| `urls` | string\[] | Searches copied from the Ad Library website, one per entry (`{ "url": "…" }` objects are accepted too). Everything in the URL is kept; filters you change are added only when the URL does not set them. Facebook page URLs here behave like entries in `pages`. |
| `keywordWithinPages` | boolean | Default `false`: every entry above is its own source. `true`: the keyword stops being a search of its own and instead filters the pages' ads, e.g. "Model Y" inside Tesla's ads. |

Provide at least one of `keyword`, `pages`, or `urls`. Each one is scraped independently and the results are combined in one dataset, so the default input (a keyword, a page, and a URL) yields three sets of ads. Empty entries are ignored.

#### Filters (apply to `keyword` and `pages`)

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `country` | string | `ALL` | ISO 3166-1 alpha-2 code (`US`, `GB`, `DE`) or `ALL` |
| `activeStatus` | string | `all` | `all`, `active`, `inactive` |
| `adType` | string | `all` | `all`, `political_and_issue_ads`, `housing_ads`, `employment_ads`, `credit_ads`. Political and issue ads carry `spend` and `reachEstimate`. |
| `mediaType` | string | `all` | `all`, `image`, `video`, `meme`, `none` |
| `datePreset` | string | — | `last24h`, `last7d`, `last14d`, `last30d`, `last90d`. Ads that were **running at any point** in the window. |
| `startDateMin` / `startDateMax` | string | — | `YYYY-MM-DD`. Explicit window; overrides `datePreset`. Same "running at any point" semantics as Facebook's own date filter. |
| `publisherPlatforms` | string\[] | `[]` | Any of `facebook`, `instagram`, `audience_network`, `messenger`, `threads`. Empty = all. |
| `contentLanguages` | string\[] | `[]` | ISO 639-1 codes (`en`, `es`, `de`). Empty = all. |
| `searchType` | string | `keyword_unordered` | `keyword_unordered` (any of the words) or `keyword_exact_phrase`. |
| `sortBy` | string | `impressions_desc` | Sent to Facebook as the sort preference. Facebook's server-rendered results currently ignore it and come back in Facebook's own order. |

#### Limits

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `limitPerSource` | integer | `10` | Max ads per keyword, page, or URL. `0` = all. |
| `maxItems` | integer | `0` | Max ads across the whole run. `0` = no limit. The run stops as soon as it is reached. |

#### Output options

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `outputMode` | string | `ad` | `ad` = one row per ad (first card flattened, all cards under `cards`). `card` = one row per creative card. |
| `includePageSummary` | boolean | `false` | Add one summary row per advertiser page (see below). |
| `includeEuTransparency` | boolean | `false` | Fetch each ad's details: EU reach with country / age / gender breakdown, targeting, payer and beneficiary, Instagram handle and followers, page verification. One extra request per ad. |
| `includeRawData` | boolean | `false` | Attach the untouched Facebook ad object as `rawData`. |
| `runTag` | string | — | Copied into the `runTag` column of every row. |
| `proxyConfiguration` | object | — | Optional proxy settings. |

***

### Output

#### Ad rows (default, `outputMode: "ad"`)

```json
{
    "adArchiveID": "899524914329334",
    "adUrl": "https://www.facebook.com/ads/library/?id=899524914329334",
    "pageName": "Wealthsimple",
    "pageID": "268452016650171",
    "pageUrl": "https://www.facebook.com/wealthsimple/",
    "pageProfilePictureUrl": "https://scontent.../pp.jpg",
    "pageLikeCount": 123456,
    "pageCategories": ["Financial service"],
    "isActive": false,
    "startDate": "2021-10-20",
    "endDate": "2022-01-12",
    "publisherPlatforms": ["FACEBOOK", "INSTAGRAM", "AUDIENCE_NETWORK", "MESSENGER"],
    "impressions": ">1M",
    "impressionsIndex": 39,
    "spend": "CA$350K - CA$400K",
    "currency": "CAD",
    "reachEstimate": ">1M",
    "categories": ["POLITICAL"],
    "isPolitical": true,
    "paidForBy": "Wealthsimple Technologies Inc.",
    "disclaimer": null,
    "collationCount": 1,
    "collationID": "165980345735977",
    "isAiGenerated": false,
    "stateMediaLabel": null,
    "targetedCountries": [],
    "totalActiveTimeSeconds": null,
    "displayFormat": "VIDEO",
    "format": "video",
    "isDCO": false,
    "primaryText": "Receive one free stock (up to $4.5k) just for signing up!",
    "headline": "Buy & sell stocks in just a few taps",
    "body": "Receive one free stock (up to $4.5k) just for signing up!",
    "cta": "Install Now",
    "ctaType": "INSTALL_MOBILE_APP",
    "destinationUrl": "http://itunes.apple.com/app/id1403491709",
    "displayDomain": "itunes.apple.com",
    "linkDescription": null,
    "imageUrl": "https://scontent.../thumb.jpg",
    "videoUrl": "https://video.../video.mp4",
    "videoThumbnailUrl": "https://scontent.../thumb.jpg",
    "cardCount": 1,
    "cards": [{ "cardIndex": 0, "headline": "Buy & sell stocks in just a few taps", "body": "…", "cta": "Install Now", "ctaType": "INSTALL_MOBILE_APP", "destinationUrl": "…", "displayDomain": "itunes.apple.com", "linkDescription": null, "imageUrl": "…", "videoUrl": "…", "videoThumbnailUrl": "…" }],
    "sourceUrl": "https://www.facebook.com/wealthsimple",
    "position": 1,
    "totalResults": 1032,
    "runTag": "2026-W39",
    "scrapedAt": "2026-09-22T16:00:00.000Z"
}
```

| Field | Description |
|-------|-------------|
| `adArchiveID`, `adUrl` | Ad Library ID and direct link |
| `pageName`, `pageID`, `pageUrl`, `pageProfilePictureUrl`, `pageLikeCount`, `pageCategories` | Advertiser page |
| `isActive`, `startDate`, `endDate` | Run status and dates (`endDate` is `null` while still running) |
| `publisherPlatforms` | Where the ad runs: `FACEBOOK`, `INSTAGRAM`, `AUDIENCE_NETWORK`, `MESSENGER`, `THREADS` |
| `impressions`, `impressionsIndex` | Impressions band (e.g. `10K - 15K`) and Facebook's ordinal index; only shown by Facebook for some ads |
| `spend`, `currency`, `reachEstimate` | Political / issue ads only |
| `categories`, `isPolitical`, `paidForBy`, `disclaimer` | Ad category labels and political disclaimers |
| `collationCount`, `collationID` | Number of near-identical variants of this ad, and their group ID |
| `isAiGenerated` | Facebook's "digitally created" flag |
| `stateMediaLabel`, `targetedCountries`, `totalActiveTimeSeconds` | Transparency labels when Facebook provides them |
| `displayFormat`, `format`, `isDCO` | Facebook's format (`IMAGE`, `VIDEO`, `CAROUSEL`, `DCO`, `DPA`…), our derived `image` / `video` / `carousel` / `text`, and whether the ad uses dynamic creative templates |
| `primaryText` | Post text above the creative (`null` for DCO, where Facebook sends template variables) |
| `headline`, `body`, `cta`, `ctaType`, `destinationUrl`, `displayDomain`, `linkDescription`, `imageUrl`, `videoUrl`, `videoThumbnailUrl` | First creative card |
| `cardCount`, `cards` | All creative cards (carousel cards or DCO variants), deduplicated |
| `sourceUrl` | The keyword URL, page, or URL you supplied |
| `position`, `totalResults` | Rank within its source, and the total number of matching ads Facebook reports (capped at 50,001) |
| `runTag`, `scrapedAt` | Your tag and the scrape timestamp |
| `rawData` | The untouched Facebook object, only when `includeRawData` is on |

#### EU transparency and payer details (`includeEuTransparency: true`)

Adds these columns to every ad row (or card row), plus the full `adDetails` object:

| Field | Description |
|-------|-------------|
| `euTotalReach` | Estimated Meta accounts in the EU that saw the ad at least once |
| `payer`, `beneficiary` | Who paid for and who benefits from the ad, as declared for EU delivery |
| `igUsername`, `igFollowers`, `pageVerification` | Advertiser's Instagram handle and followers, and Facebook verification status (`BLUE_VERIFIED`…) |
| `adDetails.euTransparency` | `targetsEu`, `totalReach`, `ageAudience {min,max}`, `genderAudience`, `locationAudience[]` (included/excluded countries, regions, cities), `reachBreakdown[]` rows of `{country, ageRange, male, female, unknown}` |
| `adDetails.payerBeneficiary` | All payer / beneficiary pairs |
| `adDetails.advertiser` | `pageLikes`, `pageCategory`, `igVerified`, `isPoliticalPage`, `isRestricted` |
| `adDetails.isTakenDown`, `violationTypes`, `isViolatingEuRules` | Enforcement flags |

Ads never shown in the EU have `euTransparency: null`. The data comes from the same request the Ad Library website makes when you click **See ad details**; it needs no login. If Facebook changes that query, the run emits one `AD_DETAILS_QUERY_INVALID` error row and continues without details.

#### Card rows (`outputMode: "card"`)

Same ad-level fields, but one row per creative card with a `cardIndex` column instead of `cardCount` / `cards`. Use this for creative analysis where each carousel card matters.

#### Page summary rows (`includePageSummary: true`)

One per advertiser page, marked `rowType: "pageSummary"`. Shown in the **Pages** view of the Output tab.

```json
{
    "rowType": "pageSummary",
    "sourceUrl": "https://www.facebook.com/ZapierApp",
    "pageName": "Zapier",
    "pageID": "309796912374932",
    "pageUrl": "https://www.facebook.com/ZapierApp/",
    "pageProfilePictureUrl": "https://scontent.../pp.jpg",
    "pageLikeCount": 56539,
    "pageCategories": ["Software"],
    "pageIsDeleted": false,
    "totalAds": 1032,
    "adsCollected": 50,
    "activeAdsCollected": 12,
    "platformBreakdown": { "FACEBOOK": 50, "INSTAGRAM": 31, "MESSENGER": 9 },
    "earliestStartDate": "2024-01-24",
    "latestStartDate": "2026-06-04",
    "runTag": "2026-W39",
    "scrapedAt": "2026-09-22T16:00:00.000Z"
}
```

`totalAds` is the count Facebook reports for your filters (so with `activeStatus: "active"` it is the number of ads currently live). The other counts describe the ads actually collected.

#### Error rows

If a source fails, the dataset gets a row with `errorCode` and `error` instead of a silent empty result. Shown in the **Errors** view.

| `errorCode` | Meaning |
|-------------|---------|
| `INVALID_PAGE` | An entry in `pages` is not a Facebook page URL, handle, or ID |
| `PAGE_ID_NOT_FOUND` | The Facebook page could not be resolved to an advertiser ID (private, deleted, or not a page) |
| `DUPLICATE_SOURCE` | Two entries resolved to the same page; its ads appear once |
| `NO_AD_DATA` | The Ad Library returned a page without ad data |
| `CHALLENGE_FAILED` | Facebook's anti-bot challenge could not be solved |
| `AD_DETAILS_QUERY_INVALID` | Facebook rejected the ad-details query (emitted once; the run continues without EU data) |
| `REQUEST_FAILED` | Network or HTTP failure after retries |

***

### How it works

The Ad Library server-renders the first page of results as JSON inside the HTML. The scraper:

1. Sends a plain HTTP request with browser-like headers (no browser, so runs are cheap and fast)
2. Solves Facebook's lightweight `__rd_verify` challenge if it is returned
3. Parses the embedded `search_results_connection` JSON
4. Follows the `end_cursor` to the next page until the limits are reached
5. For advertiser pages, first resolves the page's numeric ID, then queries the Ad Library with `view_all_page_id`

***

### Pricing

Pay per event. You are charged for what lands in your dataset, not for rows:

| Event | When it is charged |
|-------|--------------------|
| `ad` | Once per ad, in both output modes. A six-card carousel in "one row per creative card" mode is still one ad. |
| `ad-details` | Once per ad whose EU transparency details were fetched successfully (only with `includeEuTransparency`). |
| `apify-actor-start` | Once per run, by the platform. |

Error rows and page-summary rows are free. Set **Maximum cost per run** in the run options to cap spending; the actor stops cleanly when the cap is reached and you keep everything scraped up to that point.

### Proxy

The Ad Library is a public transparency tool and works without a proxy in normal use. If you scrape very large volumes and hit blocks, add residential proxies:

```json
"proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
```

# Actor input Schema

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

Searches the whole Ad Library for this term, like typing it into the Ad Library search box. Leave empty to skip the keyword search.

## `pages` (type: `array`):

Every ad each advertiser is running. One per line: a page URL (https://www.facebook.com/tesla), a handle (tesla), a numeric page ID, or an Ad Library link that contains view_all_page_id.

## `urls` (type: `array`):

Searches copied straight from the Ad Library website, one per line. Everything in the URL is kept; filters you change below are added only if the URL does not already set them. A Facebook page URL pasted here works like an advertiser page.

## `keywordWithinPages` (type: `boolean`):

Off: the keyword is a search of its own and the pages return all their ads. On: the keyword becomes a filter, so you get only the pages' ads that match it (e.g. 'Model Y' inside Tesla's ads) and no separate keyword search.

## `country` (type: `string`):

ISO 3166-1 alpha-2 country code (e.g. US, GB, DE) or ALL.

## `activeStatus` (type: `string`):

Only currently running ads, only stopped ads, or both.

## `adType` (type: `string`):

All ads, or only a regulated category. Political and issue ads carry spend and reach estimates.

## `mediaType` (type: `string`):

Filter by creative type.

## `datePreset` (type: `string`):

Only ads that were running at some point in this window. Ignored when explicit dates are given below.

## `startDateMin` (type: `string`):

YYYY-MM-DD. Only ads that were running on or after this day.

## `startDateMax` (type: `string`):

YYYY-MM-DD. Only ads that were running on or before this day.

## `publisherPlatforms` (type: `array`):

Only ads shown on these Meta platforms. Leave empty for all.

## `contentLanguages` (type: `array`):

ISO 639-1 codes, one per line (en, es, de, fr, pt…). Leave empty for all languages.

## `searchType` (type: `string`):

'Any of the words' matches ads containing the words in any order. 'Exact phrase' matches the words together, in order.

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

Sent to Facebook as the sort preference. Note: Facebook's server-rendered results currently ignore it and come back in Facebook's own relevance order.

## `limitPerSource` (type: `integer`):

Maximum ads to collect for each keyword, page, or URL. Set 0 to collect all of them.

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

Stop the run after this many ads across all sources. 0 = no limit. Useful to cap cost when scraping many pages.

## `outputMode` (type: `string`):

'One row per ad' flattens the first creative card into the row and nests every card under 'cards'. 'One row per creative card' emits carousel cards as separate rows.

## `includePageSummary` (type: `boolean`):

For each page in 'Facebook pages', add one row with the total number of matching ads, how many were collected, active count, platform breakdown, and earliest/latest start dates. See the 'Pages' view in the Output tab.

## `includeEuTransparency` (type: `boolean`):

Fetch each ad's details page: EU reach with a country / age / gender breakdown, targeting (locations, age range, gender), payer and beneficiary, Instagram handle and followers, page verification. Costs one extra request per ad, so runs take longer.

## `includeRawData` (type: `boolean`):

Attach the untouched Facebook ad object to every row as 'rawData'. Increases dataset size.

## `runTag` (type: `string`):

Free text copied into the 'runTag' column of every row. Handy for joining several runs in a spreadsheet.

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

Optional. The Ad Library is a public tool and normally works without a proxy. Use residential proxies only if you encounter blocks.

## Actor input object example

```json
{
  "keyword": "Tesla",
  "pages": [
    "https://www.facebook.com/tesla"
  ],
  "urls": [
    "https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=US&q=tesla&search_type=keyword_unordered&media_type=all"
  ],
  "keywordWithinPages": false,
  "country": "ALL",
  "activeStatus": "all",
  "adType": "all",
  "mediaType": "all",
  "datePreset": "",
  "publisherPlatforms": [],
  "contentLanguages": [],
  "searchType": "keyword_unordered",
  "sortBy": "impressions_desc",
  "limitPerSource": 10,
  "maxItems": 0,
  "outputMode": "ad",
  "includePageSummary": false,
  "includeEuTransparency": false,
  "includeRawData": false
}
```

# 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 = {
    "keyword": "Tesla",
    "pages": [
        "https://www.facebook.com/tesla"
    ],
    "urls": [
        "https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=US&q=tesla&search_type=keyword_unordered&media_type=all"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("practicaltools/facebook-ad-library-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 = {
    "keyword": "Tesla",
    "pages": ["https://www.facebook.com/tesla"],
    "urls": ["https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=US&q=tesla&search_type=keyword_unordered&media_type=all"],
}

# Run the Actor and wait for it to finish
run = client.actor("practicaltools/facebook-ad-library-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 '{
  "keyword": "Tesla",
  "pages": [
    "https://www.facebook.com/tesla"
  ],
  "urls": [
    "https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=US&q=tesla&search_type=keyword_unordered&media_type=all"
  ]
}' |
apify call practicaltools/facebook-ad-library-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,practicaltools/facebook-ad-library-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/iPPhmZhgohnHtznlY/builds/eL1ErXIZYnbiRbQOf/openapi.json
