# Link Status Checker (`axiomworks/broken-link-checker`) Actor

Check internal and external links discovered while crawling user-supplied start URLs. Each result includes the target, status category, HTTP code, final URL, redirect chain, anchor text and source page. The checker uses HEAD requests with a GET fallback and records redirect hops for review.

- **URL**: https://apify.com/axiomworks/broken-link-checker.md
- **Developed by:** [Axiom Works](https://apify.com/axiomworks) (community)
- **Categories:** SEO tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.79 / 1,000 results

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

**Returns:** one row per link per crawled page with `url`, `statusCode`, `linkStatus`, `isBroken`, `anchorText`, `sourcePage`, `redirectChain` and `finalUrl`.
**Input:** `{"startUrls": [{"url": "https://crawler-test.com/links/broken_links_internal"}], "maxDepth": 1, "maxPages": 20, "maxItems": 500}`
**Best for:** finding 404s before an SEO audit, checking outbound links after a site migration, QA of redirect chains.

```json
{
    "id": "d6af6e0cd46f477b",
    "url": "https://crawler-test.com/",
    "anchorText": "Crawler Test two point oh!",
    "sourcePage": "https://crawler-test.com/links/broken_links_internal",
    "linkType": "internal",
    "statusCode": 200,
    "isBroken": false,
    "linkStatus": "ok",
    "redirectChain": [],
    "finalUrl": "https://crawler-test.com/",
    "method": "HEAD"
}
```

### What does Broken Link Checker do?

Broken Link Checker crawls a website from one or more start URLs and checks every link it finds. It stays on the start site (subdomains included by default), follows internal pages up to the depth and page limits you set, and checks each internal and outbound link with an HTTP HEAD request, falling back to GET when a server doesn't answer HEAD properly. Redirects are followed one hop at a time, so you see the whole redirect chain and where the link ends up.

You get one row for every link on every crawled page: the link URL as written and as resolved, the anchor text, the page it was found on, the final HTTP status code, the redirect chain, the final URL, the content type, the response time and a plain category such as `ok`, `redirect`, `broken`, `blocked`, `server_error`, `network_error` or `redirect_loop`. A link that appears on ten pages gives ten rows (one per page, so you know where to fix it), but it is checked only once per run.

It works on any public website and needs no login, no API key and no browser. Typical jobs are a broken link report for an SEO audit, checking a site after a migration or redesign, monitoring outbound links in a blog or documentation site, and finding long redirect chains that slow pages down. It is a website link checker and dead link finder that you can run on a schedule or call from an AI agent.

### What data can you get from a website link check?

| Field | Description | Example |
|---|---|---|
| `id` | Stable record ID: first 16 hex characters of sha1(sourcePage + "|" + url) | `b2377af70dd16694` |
| `url` | The link target that was checked: the href resolved to an absolute URL, #fragment removed | `https://crawler-test.com/links/not_found/foo1` |
| `href` | The href attribute exactly as written in the page | `/links/not_found/foo1` |
| `anchorText` | Visible text of the link, whitespace collapsed; null for image-only links | `Broken Internal Link 1` |
| `rel` | The link's rel attribute, null when absent | `nofollow` |
| `occurrences` | How many times the page links to this URL | `1` |
| `sourcePage` | Final URL of the crawled page the link was found on | `https://crawler-test.com/links/broken_links_internal` |
| `sourceDepth` | Crawl depth of the source page (0 = a start URL) | `0` |
| `linkType` | `internal` (same site or subdomain) or `external` | `internal` |
| `statusCode` | Final HTTP status code; null on a network error or redirect loop | `404` |
| `isBroken` | true when statusCode is null or 400 or higher | `true` |
| `linkStatus` | `ok`, `redirect`, `broken`, `blocked`, `server_error`, `network_error` or `redirect_loop` | `broken` |
| `redirectCount` | Number of redirect hops followed | `4` |
| `redirectChain` | Every redirect hop in order as `{url, statusCode}` | `[{"url": "https://crawler-test.com/redirects/reverse_redirect/4", "statusCode": 301}]` |
| `finalUrl` | Where the link ends up after redirects | `https://crawler-test.com/redirects/redirect_target` |
| `contentType` | MIME type of the final response | `text/html` |
| `method` | `HEAD`, or `GET` when the server needed the GET fallback | `HEAD` |
| `error` | Network error code when no response came back (`ENOTFOUND`, `TOO_MANY_REDIRECTS`...) | `ENOTFOUND` |
| `responseTimeMs` | Milliseconds the check took, summed over redirect hops | `317` |
| `checkedAt` | ISO 8601 time the check finished | `2026-10-13T01:04:53.940Z` |
| `sourceUrl` | The page the link was found on (same as `sourcePage`) | `https://crawler-test.com/links/broken_links_internal` |

Requests to each host start at least 250 milliseconds apart, with at most two requests in flight per host and the overall `maxConcurrency` limit. Results remain in page order, and repeated target URLs share one cached check across pages.

At the end of every run a `SUMMARY` record in the run's key-value store lists the start URLs, the number of pages crawled, links found, unique URLs checked, broken links, redirects, blocked links and network errors, the pages that could not be crawled (`pageErrors`) and why the crawl stopped (`maxItems`, `maxPages` or `exhausted`).

#### What the link statuses mean

| linkStatus | When | isBroken |
|---|---|---|
| `ok` | Status below 400 and no redirect | false |
| `redirect` | The link redirected at least once and ended below 400 | false |
| `broken` | Final status 400-499 (except 403 and 429) | true |
| `blocked` | Final status 403, 429 or 999: usually bot protection rather than a dead page | true |
| `server_error` | Final status 500 or higher | true |
| `network_error` | No response: DNS failure, refused connection, timeout, bad certificate | true |
| `redirect_loop` | More redirect hops than `maxRedirects` | true |

### How to use Broken Link Checker

1. Open Broken Link Checker in Apify Console and go to the Input tab.
2. Add one or more start URLs. A full URL (`https://www.example.com/blog/`) or just a host (`example.com`) both work.
3. Set how far to crawl: `maxDepth` (clicks from the start page), `maxPages` (pages scanned for links) and `maxItems` (rows returned).
4. Optionally switch off `checkExternalLinks` to check only your own site, or switch on `onlyBroken` to get only the problems.
5. Click Start. When the run finishes, open the Output tab and filter by `linkStatus` or `isBroken`, or export the rows as JSON, CSV, Excel, XML or HTML.

To audit exactly the pages you publish, give your sitemap, for example `https://example.com/sitemap.xml`, as a start URL. Its page URLs are checked directly, so `maxDepth` 0 checks just the links on those pages. Gzipped sitemaps (`.xml.gz`) are not read.

Start with the defaults (`maxDepth` 1, `maxPages` 20). They check the start page and the pages it links to, which covers the navigation of most small sites in a minute or two.

For a full site audit, raise `maxPages` and `maxItems` together. `maxItems` is shared across all start URLs and pages; the run stops as soon as that many rows are saved.

Use `excludeUrlPatterns` to skip logout links, admin areas, calendars or faceted search pages that would otherwise produce thousands of near-identical URLs.

Schedule the Actor weekly in the Schedules tab to catch new broken links early.

### Input

| Field | Type | Required | Description |
|---|---|---|---|
| `startUrls` | array | Yes | Websites or pages to start from, as `[{"url": "..."}]` or plain strings. A bare host gets `https://`. A URL ending in `.xml` is read as a sitemap (or sitemap index, first 5 child sitemaps): its page URLs, up to `maxPages`, are checked as start pages. The legacy keys `url` / `startUrl` (one string) and `urls` (list) are accepted too. |
| `maxDepth` | integer | No | Clicks deep to crawl, 0-10, default 1. 0 checks only the links on the start pages. |
| `maxPages` | integer | No | Maximum HTML pages crawled across all start URLs, 1-10000, default 20. |
| `maxItems` | integer | No | Maximum link rows returned, 1-1000000, default 500. |
| `checkExternalLinks` | boolean | No | Check and return links to other websites, default true. They are never crawled. |
| `includeSubdomains` | boolean | No | Treat subdomains as the same site, default true. |
| `onlyBroken` | boolean | No | Return only rows with `isBroken` true, default false. Everything is still crawled and checked. |
| `excludeUrlPatterns` | array of strings | No | Regular expressions; matching URLs are not crawled, checked or returned. Default: none. |
| `maxRedirects` | integer | No | Redirect hops followed per link, 0-30, default 10. |
| `requestTimeoutSecs` | integer | No | Seconds to wait for a response, 3-120, default 15. |
| `maxConcurrency` | integer | No | Checks in flight at once, 1-20, default 5 (never more than 2 per host). |
| `userAgent` | string | No | User-Agent header. Default: a current desktop Chrome User-Agent. |
| `proxyConfiguration` | object | No | Proxy for every request. Default: no proxy. |

```json
{
    "startUrls": [
        { "url": "https://crawler-test.com/links/broken_links_internal" },
        "iana.org"
    ],
    "maxDepth": 1,
    "maxPages": 10,
    "maxItems": 200,
    "checkExternalLinks": true,
    "includeSubdomains": true,
    "onlyBroken": false,
    "excludeUrlPatterns": ["logout", "/wp-admin/"],
    "maxRedirects": 10,
    "requestTimeoutSecs": 15,
    "maxConcurrency": 5,
    "proxyConfiguration": { "useApifyProxy": false }
}
```

### Output

Each row is one link on one page. These rows come from a real run on crawler-test.com and iana.org. You can download the dataset as JSON, CSV, Excel, XML, RSS or HTML, or read it through the API.

```json
[
    {
        "id": "6a4540477f1fd18d",
        "url": "https://crawler-test.com/redirects/reverse_redirect/4",
        "href": "/redirects/reverse_redirect/4",
        "anchorText": "4 Redirects Chain Link",
        "rel": null,
        "occurrences": 1,
        "sourcePage": "https://crawler-test.com/redirects/url_redirect_chains",
        "sourceDepth": 0,
        "linkType": "internal",
        "statusCode": 200,
        "isBroken": false,
        "linkStatus": "redirect",
        "redirectCount": 4,
        "redirectChain": [
            { "url": "https://crawler-test.com/redirects/reverse_redirect/4", "statusCode": 301 },
            { "url": "https://crawler-test.com/redirects/reverse_redirect/3", "statusCode": 301 },
            { "url": "https://crawler-test.com/redirects/reverse_redirect/2", "statusCode": 301 },
            { "url": "https://crawler-test.com/redirects/reverse_redirect/1", "statusCode": 301 }
        ],
        "finalUrl": "https://crawler-test.com/redirects/redirect_target",
        "contentType": "text/html",
        "method": "HEAD",
        "error": null,
        "responseTimeMs": 1365,
        "checkedAt": "2026-10-13T01:20:16.614Z",
        "sourceUrl": "https://crawler-test.com/redirects/url_redirect_chains"
    },
    {
        "id": "09a5c607ebe781fb",
        "url": "https://www.icann.org/",
        "href": "https://www.icann.org/",
        "anchorText": "ICANN",
        "rel": null,
        "occurrences": 1,
        "sourcePage": "https://www.iana.org/",
        "sourceDepth": 0,
        "linkType": "external",
        "statusCode": 403,
        "isBroken": true,
        "linkStatus": "blocked",
        "redirectCount": 0,
        "redirectChain": [],
        "finalUrl": "https://www.icann.org/",
        "contentType": "text/html",
        "method": "GET",
        "error": null,
        "responseTimeMs": 68,
        "checkedAt": "2026-10-13T01:19:28.030Z",
        "sourceUrl": "https://www.iana.org/"
    }
]
```

The Output tab's Overview shows the most useful columns (status, link, anchor text, source page, link type, redirects, final URL, error); the All fields view shows everything.

### How much does it cost to check links on a website?

Broken Link Checker is charged per result, where one result is one link row. You pay only for the rows returned, and `maxItems` caps how many that can be. With `onlyBroken` on you pay only for broken rows, even though every link is checked. See the Pricing tab for the current price.

### Use with AI agents (MCP)

Connect Broken Link Checker to Claude, Cursor or any MCP client through the Apify MCP server:

```json
{
    "mcpServers": {
        "apify": {
            "url": "https://mcp.apify.com/?tools=axiomworks/broken-link-checker"
        }
    }
}
```

Example prompts:

1. "Check https://www.example.com for broken links two clicks deep and list every 404 with the page it's on."
2. "Find all outbound links on our blog at blog.example.com that redirect more than twice, with their final URLs."
3. "Run a broken link check on example.org with onlyBroken on and group the results by linkStatus."

### Integrations and API

Run Broken Link Checker from your own code with the Apify API. Set `APIFY_TOKEN` to your Apify API token (send it in the `Authorization` header, never in the URL).

**Python**

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")
run = client.actor("axiomworks/broken-link-checker").call(run_input={
    "startUrls": [{"url": "https://crawler-test.com/links/broken_links_internal"}],
    "maxDepth": 1,
    "maxItems": 500,
    "onlyBroken": True,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["linkStatus"], item["statusCode"], item["url"], "on", item["sourcePage"])
```

**JavaScript**

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

const client = new ApifyClient({ token: '<YOUR_API_TOKEN>' });
const run = await client.actor('axiomworks/broken-link-checker').call({
    startUrls: [{ url: 'https://crawler-test.com/links/broken_links_internal' }],
    maxDepth: 1,
    maxItems: 500,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
const broken = items.filter((item) => item.isBroken);
```

**cURL**

```bash
curl -X POST "https://api.apify.com/v2/acts/axiomworks~broken-link-checker/run-sync-get-dataset-items" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"startUrls": [{"url": "https://crawler-test.com/links/broken_links_internal"}], "maxDepth": 1, "maxItems": 100}'
```

The Integrations tab connects runs to Make, Zapier, n8n, Google Sheets, Slack, email and webhooks, so a weekly scheduled check can send its broken links straight to your team.

### FAQ

**How is a link judged broken?**
A link is broken (`isBroken` true) when its final HTTP status is 400 or higher, when no response came back at all (DNS failure, refused connection, timeout, certificate error) or when it redirects more often than `maxRedirects`. The `linkStatus` field tells these cases apart.

**Why are some working links reported as `blocked`?**
Many large sites (social networks, sites behind Cloudflare and similar services) answer automated requests with 403, 429 or LinkedIn's 999 even when the page works in a browser. These rows get `linkStatus` `blocked` so you can filter them out or check them by hand. They still count as `isBroken` true because the checker could not confirm the page works.

**Why does a Facebook link show as broken?**
Facebook often redirects anonymous visitors to a login page that answers 400. The row shows the redirect chain and the final URL, so you can see what happened. Treat social profile links with care.

**Why did a page that says "not found" come back as `ok`?**
Some sites show a "page not found" message with HTTP status 200 (a soft 404). The checker reports the HTTP status the server sends, so such pages count as working.

**Why did my run return 0 results?**
If the start URL itself can't be loaded (wrong address, the site is down, or it blocks the request) the run ends with the status message "Start URL unreachable" and the reason, and the SUMMARY record lists it under `pageErrors`. If the page loads but has no links, the run finishes with 0 results and says so. With `onlyBroken` on, 0 results means no broken links were found.

**Does it crawl other websites?**
No. Only pages on the start URL's site (and its subdomains, unless you turn `includeSubdomains` off) are crawled. Links to other sites are checked once and returned, never crawled.

**Does it read robots.txt or run JavaScript?**
It does not read robots.txt, and it reads the HTML the server sends without running JavaScript, so links that a page adds with JavaScript after loading are not found.

**How fast is it?**
It is polite by default: at most 2 requests at a time to one host with a short pause between them, and 5 checks in flight overall. A start page plus a few hundred links usually takes one to two minutes.

### Is it legal to crawl a website and check its links?

Broken Link Checker requests only public pages, the same way a browser or a search engine does, and does not log in anywhere. Checking links on your own site, or on public pages, is normal practice for site maintenance and SEO. Check the terms of sites you don't own before crawling them in depth, and keep the default polite request rate. This is not legal advice.

Broken Link Checker is an independent tool. It is not affiliated with, endorsed by or sponsored by any of the websites it checks.

### Related Actors

| Actor | What it does |
|---|---|
| [Semrush SEO Metrics Scraper](https://apify.com/axiomworks/semrush-domain-overview-scraper) | Domain-level SEO metrics to go with a link audit |
| [Google Search SERP Scraper](https://apify.com/axiomworks/google-search-results-scraper) | Google search results for checking which of your pages rank |

### Feedback

Found a bug or need a field that isn't here? Open an issue on the Issues tab and we'll look at it.

# Actor input Schema

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

Required: websites or pages to start from, as \[{"url": "https://example.com/"}] or plain strings (up to 10 is sensible). A URL ending in .xml is read as a sitemap: its page URLs (up to maxPages) are checked as start pages. A bare host like 'iana.org' gets https://. The crawl stays on each start URL's site (subdomains included by default). A dead or blocked start URL returns 0 rows for it and is named in the status message and the SUMMARY record.

## `maxDepth` (type: `integer`):

How many clicks deep to crawl from the start URLs, 0-10, default 1. 0 checks only the links on the start page(s); 1 also crawls the internal pages they link to, and so on. Bounded by maxPages and maxItems.

## `maxPages` (type: `integer`):

Maximum number of HTML pages fetched and scanned for links, across all start URLs, 1-10000, default 20. Every link on a crawled page is checked; each unique URL is checked only once per run.

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

Maximum number of link rows to return across all start URLs and pages, 1-1000000, default 500. One row = one link on one page. The run stops as soon as this many rows are saved, and you are charged only for rows returned.

## `checkExternalLinks` (type: `boolean`):

Default true: links to other websites are checked and returned (they are never crawled). false = only links on the same site are checked and returned.

## `includeSubdomains` (type: `boolean`):

Default true: blog.example.com counts as the same site as example.com (crawled, linkType 'internal'). false = only the exact start host counts as internal (www. is ignored either way).

## `onlyBroken` (type: `boolean`):

Default false: every link is returned. true = only rows with isBroken true (status 400 or higher, blocked, network error or redirect loop); the whole site is still crawled and checked, and maxItems counts broken rows only.

## `excludeUrlPatterns` (type: `array`):

Regular expressions (case-insensitive); links whose URL matches any of them are neither crawled, checked nor returned, e.g. 'logout' or '/wp-admin/'. Default: none.

## `maxRedirects` (type: `integer`):

Redirect hops to follow per link, 0-30, default 10. A link that redirects more often is reported as linkStatus 'redirect_loop' with error TOO_MANY_REDIRECTS.

## `requestTimeoutSecs` (type: `integer`):

Seconds to wait for a response before a link counts as a network error, 3-120, default 15 (connecting is capped at 10 s).

## `maxConcurrency` (type: `integer`):

Link checks in flight at once, 1-20, default 5. Never more than 2 at a time per host, with a 200-500 ms pause between requests to the same host, so sites are not hammered.

## `userAgent` (type: `string`):

User-Agent header for every request. Empty (default) sends a current desktop Chrome User-Agent.

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

Default: no proxy, the checks run from Apify's servers. If a start page answers 403/429 it is retried once through Apify Proxy (datacenter, then residential). Set a proxy here to send every request through it. Single links that answer 403/429/999 are reported as 'blocked'.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://crawler-test.com/links/broken_links_internal"
    }
  ],
  "maxDepth": 1,
  "maxPages": 3,
  "maxItems": 40,
  "checkExternalLinks": true,
  "includeSubdomains": true,
  "onlyBroken": false,
  "excludeUrlPatterns": [],
  "maxRedirects": 10,
  "requestTimeoutSecs": 15,
  "maxConcurrency": 5,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `overview` (type: `string`):

Dataset with one item per (source page, link) pair, in crawl order.

# 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://crawler-test.com/links/broken_links_internal"
        }
    ],
    "maxDepth": 1,
    "maxPages": 3,
    "maxItems": 40,
    "checkExternalLinks": true,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("axiomworks/broken-link-checker").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://crawler-test.com/links/broken_links_internal" }],
    "maxDepth": 1,
    "maxPages": 3,
    "maxItems": 40,
    "checkExternalLinks": True,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("axiomworks/broken-link-checker").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://crawler-test.com/links/broken_links_internal"
    }
  ],
  "maxDepth": 1,
  "maxPages": 3,
  "maxItems": 40,
  "checkExternalLinks": true,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call axiomworks/broken-link-checker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,axiomworks/broken-link-checker"
        }
    }
}
```

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/4ShL2WQQPU5jr7Fpe/builds/Txhvs1QtNXQQcT26y/openapi.json
