# HTTP Headers & Redirect Checker (`plainpipe/http-headers-checker`) Actor

Check HTTP headers and redirect chains: security score with values to set, CSP, HSTS, CORS and cache checks. Use when you need to audit headers or redirects.

- **URL**: https://apify.com/plainpipe/http-headers-checker.md
- **Developed by:** [Plain Pipe](https://apify.com/plainpipe) (community)
- **Categories:** SEO tools, Developer tools
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.90 / 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.

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

## HTTP Headers & Redirect Checker

Check URLs for their full redirect chain, final status code and response headers. Every URL gets a 0-100 security-header score with an A+ to F grade, the exact value to set for each weak or missing header, and CSP, HSTS, CORS, caching, compression and HTTP/2 / HTTP/3 checks.

**Use this when:** you need to verify redirects, final status codes, or security, CORS and cache headers for a list of URLs, and want to know what to change.

### What it does

Give it a list of URLs (or an Apify dataset of URLs). For each one it follows redirects hop by hop and returns one row with:

- **Redirect chain**: every hop with status code, `Location`, response time and server; redirect loops and over-long chains are detected and reported, HTTPS-to-HTTP downgrades and temporary (302/307) redirects are flagged.
- **Security score and grade**: seven headers are scored with partial credit for weak values (see the table below), minus up to 10 points for version disclosure in `Server` / `X-Powered-By`. Each header comes with its status (`good`, `weak`, `invalid`, `missing`), notes and the value to set.
- **CSP parsing**: directives found, `'unsafe-inline'` (ignored when a nonce, hash or `'strict-dynamic'` is present), `'unsafe-eval'`, wildcard or scheme-only script sources, missing `default-src`, `object-src`, `base-uri`, `frame-ancestors`.
- **HSTS details**: `max-age` in seconds and days, `includeSubDomains`, `preload`, and whether the header meets preload-list rules.
- **CORS**: `Access-Control-Allow-Origin`, methods, headers, max-age, plus warnings (any origin, the `null` origin, echoed origin without `Vary: Origin`). Send your own `Origin` to see how the server answers it.
- **Caching**: `Cache-Control` split into fields (`max-age`, `s-maxage`, `no-store`, `private`, `immutable` and more), `ETag`, `Last-Modified`, `Age`, `Vary`, CDN cache status, and whether the response is cacheable in browsers and in shared caches.
- **Compression and protocol**: `Content-Encoding` (br, gzip) for an offered `br, gzip, deflate`, HTTP/2 support (TLS ALPN handshake), HTTP/3 advertised in `Alt-Svc`, TLS version.
- **Plain lists**: `issues` (every finding as a sentence) and `recommendations` (header, value to set, points gained), plus all final response headers.

### Use cases

- Verify 301 redirects after a site migration or a domain change, including multi-hop chains and loops.
- Confirm that `http://` and bare-domain URLs upgrade to HTTPS, with HSTS set correctly.
- Audit security headers across many sites and hand developers the exact values to set.
- Check `Cache-Control`, CDN hits and compression on key pages or assets after a deploy.
- Test CORS answers for a given origin, or compare desktop and mobile responses.

### How to use it

1. Paste URLs into **URLs**, one per line, or set **Read URLs from a dataset** to the ID of a dataset (for example the output of a sitemap run). Start a URL with `http://` to test the HTTPS upgrade.
2. Optionally pick a **Request method**, a **User-Agent**, extra request headers or an **Origin**.
3. Choose **Output format**: `full` for nested JSON or `flat` for spreadsheet-ready columns.
4. Run the Actor. Results land in the dataset; export them as JSON, CSV or Excel, or read them through the Apify API. The **Issues and fixes** view lists findings and values to set per URL.

### Input

| Field | What it is | Default | Example |
|---|---|---|---|
| `urls` | URLs to check. A bare domain is read as `https://`. Invalid entries are skipped with a log warning. | none | `["http://example.com/old-page", "example.org"]` |
| `datasetId` | ID or name of an Apify dataset to read URLs from (combined with `urls`). | none | `"aBcD1234efGh5678"` |
| `datasetUrlField` | Field of each dataset item that holds the URL. | `url` | `loc` |
| `method` | `HEAD` (lighter) or `GET`. If a server refuses HEAD (405 or 501), that URL is retried with GET. | `HEAD` | `GET` |
| `userAgent` | `bot`, `desktop` or `mobile`. The browser-shaped strings still end in `SiteCheckBot/1.0 (Apify Actor)`. | `bot` | `mobile` |
| `headers` | Extra request headers as a JSON object. Headers carrying secrets (Authorization, API keys, tokens) are refused. | `{}` | `{"Accept-Language": "de-DE"}` |
| `origin` | Sent as the `Origin` request header to test CORS. | none | `example.org` |
| `maxRedirects` | Stop following after this many redirects (0 to 30). | `10` | `5` |
| `includeHopHeaders` | Add all response headers to every hop of the chain. | `false` | `true` |
| `checkHttp2` | One TLS handshake to the final host to read HTTP/2 (ALPN) and the TLS version. | `true` | `false` |
| `outputFormat` | `full` (nested) or `flat` (plain columns, lists joined with `\|`). | `full` | `flat` |
| `maxConcurrency` | URLs checked in parallel (1 to 5). The same host still gets at most one request per second. | `5` | `3` |
| `timeoutSecs` | Timeout per request in seconds (1 to 120). | `15` | `30` |
| `maxItems` | Check at most this many URLs. | `100` | `1000` |

Either `urls` or `datasetId` must give at least one valid URL.

Example input:

```json
{
  "urls": ["http://apify.com", "https://docs.apify.com"],
  "method": "HEAD",
  "userAgent": "bot",
  "outputFormat": "full",
  "maxItems": 2
}
```

### Scoring

| Header | Max points | Full points when |
|---|---|---|
| Strict-Transport-Security | 25 | `max-age` of at least one year (180 days or more gives 20, less gives 10) |
| Content-Security-Policy | 25 | enforced policy without `'unsafe-inline'`, `'unsafe-eval'`, broad script sources, and with `default-src`, `object-src`, `base-uri` (Report-Only alone gives 5) |
| X-Frame-Options | 15 | `DENY` or `SAMEORIGIN`, or CSP `frame-ancestors` |
| X-Content-Type-Options | 10 | `nosniff` |
| Referrer-Policy | 10 | `no-referrer`, `same-origin`, `strict-origin` or `strict-origin-when-cross-origin` |
| Permissions-Policy | 10 | present (legacy Feature-Policy alone gives 5) |
| Cross-Origin-Opener-Policy | 5 | `same-origin` or `same-origin-allow-popups` |

Version numbers in `Server`, `X-Powered-By` and similar headers cost up to 10 points. Grade: A+ 95 or more, A 85, B 70, C 55, D 40, F below 40. A final URL on plain HTTP is always F. Deprecated headers (`X-XSS-Protection` other than `0`, `Expect-CT`, `Public-Key-Pins`) are listed in `issues` without changing the score.

### Output

One row per URL. A real row from a run on `http://apify.com` on 2026-11-04 (the long CSP value, `scriptSources` and `headers` are shortened here; the dataset holds every value):

```json
{
  "url": "http://apify.com/",
  "finalUrl": "https://apify.com/",
  "finalStatusCode": 200,
  "redirectCount": 1,
  "redirectLoop": false,
  "tooManyRedirects": false,
  "redirectChain": [
    { "url": "http://apify.com/", "statusCode": 301, "location": "https://apify.com/", "timeMs": 125, "server": "CloudFront" },
    { "url": "https://apify.com/", "statusCode": 200, "location": null, "timeMs": 1214, "server": null }
  ],
  "httpsUpgrade": true,
  "method": "HEAD",
  "userAgent": "bot",
  "responseTimeMs": 1214,
  "totalTimeMs": 1340,
  "contentType": "text/html; charset=utf-8",
  "cacheControl": "private, no-cache, no-store, max-age=0, must-revalidate",
  "contentEncoding": null,
  "securityGrade": "C",
  "securityScore": 62,
  "securityHeadersPresent": ["Strict-Transport-Security", "Content-Security-Policy", "X-Frame-Options", "X-Content-Type-Options"],
  "securityHeadersMissing": ["Referrer-Policy", "Permissions-Policy", "Cross-Origin-Opener-Policy"],
  "issues": [
    "Referrer-Policy is missing.",
    "Cross-Origin-Opener-Policy is missing.",
    "Strict-Transport-Security: max-age is 182 days; one year (31536000) is the common baseline.",
    "Strict-Transport-Security: No includeSubDomains: subdomains can still be reached over HTTP.",
    "Content-Security-Policy: script-src allows 'unsafe-inline' without a nonce or hash, so injected inline scripts run.",
    "Content-Security-Policy: script-src allows 'unsafe-eval' (eval and new Function).",
    "Permissions-Policy: Only the legacy Feature-Policy header is sent.",
    "X-XSS-Protection \"1; mode=block\" is deprecated and can introduce leaks; set \"0\" or remove it, and rely on CSP.",
    "Expect-CT is obsolete; it can be removed.",
    "CORS allows any origin (*): fine for public assets, review it for private APIs.",
    "no-store: nothing is cached, every visit is a full request.",
    "No Content-Encoding on the HEAD response; some servers only compress GET, re-check with method GET."
  ],
  "recommendations": [
    { "header": "Strict-Transport-Security", "set": "max-age=31536000; includeSubDomains", "gain": 5 },
    { "header": "Content-Security-Policy", "set": "replace 'unsafe-inline' in script-src with nonces or hashes; remove 'unsafe-eval'", "gain": 13 },
    { "header": "Referrer-Policy", "set": "strict-origin-when-cross-origin", "gain": 10 },
    { "header": "Permissions-Policy", "set": "camera=(), microphone=(), geolocation=()", "gain": 5 },
    { "header": "Cross-Origin-Opener-Policy", "set": "same-origin (or same-origin-allow-popups if you open third-party windows)", "gain": 5 }
  ],
  "securityHeaders": [
    {
      "header": "Strict-Transport-Security", "present": true, "value": "max-age=15768000",
      "score": 20, "maxScore": 25, "status": "weak",
      "notes": ["max-age is 182 days; one year (31536000) is the common baseline.", "No includeSubDomains: subdomains can still be reached over HTTP."],
      "recommendation": "max-age=31536000; includeSubDomains"
    },
    { "header": "X-Frame-Options", "present": true, "value": "SAMEORIGIN", "score": 15, "maxScore": 15, "status": "good", "notes": [], "recommendation": null }
  ],
  "hsts": { "maxAge": 15768000, "maxAgeDays": 182, "includeSubDomains": false, "preload": false, "preloadReady": false },
  "csp": {
    "directives": ["default-src", "connect-src", "img-src", "frame-src", "style-src", "style-src-elem", "style-src-attr", "script-src", "script-src-elem", "font-src", "form-action", "child-src", "media-src", "frame-ancestors", "base-uri"],
    "scriptSources": ["'self'", "'unsafe-eval'", "..."],
    "unsafeInline": true, "unsafeEval": true, "usesNonceOrHash": false, "strictDynamic": false,
    "broadScriptSources": [], "missingDirectives": [],
    "frameAncestors": "'self' https://cms.apify.com", "upgradeInsecureRequests": false, "reportsTo": false
  },
  "cors": {
    "enabled": true, "allowOrigin": "*", "allowCredentials": null, "allowMethods": null, "allowHeaders": null,
    "exposeHeaders": "Link", "maxAge": null, "crossOriginResourcePolicy": null, "crossOriginEmbedderPolicy": null,
    "warnings": ["CORS allows any origin (*): fine for public assets, review it for private APIs."]
  },
  "caching": {
    "cacheControl": "private, no-cache, no-store, max-age=0, must-revalidate", "maxAge": 0, "sMaxAge": null,
    "noStore": true, "noCache": true, "private": true, "public": false, "immutable": false, "mustRevalidate": true,
    "etag": null, "lastModified": null, "age": null, "vary": "Accept-Encoding", "cacheStatus": "Miss from cloudfront",
    "servedFromCache": false, "browserCacheable": false, "sharedCacheable": false, "revalidatable": false
  },
  "compression": { "contentEncoding": null, "compressed": false, "brotli": false, "compressible": true },
  "protocol": { "altSvc": "h3=\":443\"; ma=86400", "http3Advertised": true, "alpn": "h2", "tlsVersion": "TLSv1.3", "http2Supported": true },
  "disclosure": { "penalty": 0 },
  "headers": { "content-type": "text/html; charset=utf-8", "strict-transport-security": "max-age=15768000", "x-frame-options": "SAMEORIGIN" },
  "checkedAt": "2026-11-04T09:46:15.860Z"
}
```

In the same run `https://docs.apify.com` scored 40/100 (grade D): no CSP, X-Content-Type-Options, Referrer-Policy, Permissions-Policy or Cross-Origin-Opener-Policy. The same URL `https://apify.com` with `"method": "GET"` reports `contentEncoding: "gzip"`, which HEAD did not show.

With `"outputFormat": "flat"` the same facts come as plain columns, for example `redirectChain: "301 http://apify.com/ -> 200 https://apify.com/"`, `hstsMaxAge`, `cspUnsafeInline`, `corsAllowOrigin`, `cacheMaxAge`, `http2Supported`, `issues` and `recommendations` as `|`-joined text.

A redirect loop is a result too: the row has `redirectLoop: true`, the hops up to the repeated URL, `finalUrl` / `finalStatusCode` of the last response received (a 3xx), no security grade, and the loop in `issues`. Chains longer than `maxRedirects` look the same with `tooManyRedirects: true`.

| Field | Meaning |
|---|---|
| `finalUrl`, `finalStatusCode` | Where the chain ends and that response's status code. |
| `redirectCount`, `redirectChain` | Number of redirects and every hop with status, `Location`, time and server (all headers with `includeHopHeaders`). |
| `redirectLoop`, `tooManyRedirects` | The chain revisits a URL, or is longer than `maxRedirects`. |
| `httpsUpgrade` | `true` when an `http://` URL ended on `https://`. |
| `securityScore`, `securityGrade` | 0-100 and A+ to F, see Scoring. |
| `securityHeaders` | Per-header value, score, status, notes and the value to set. |
| `recommendations` | Only the headers to change: value to set and points gained. |
| `issues` | Every finding as one sentence: chain, security, CORS, cache, compression. |
| `hsts`, `csp`, `cors`, `caching`, `compression`, `protocol`, `disclosure` | Parsed details per area. |
| `headers` | All final response headers, lower-cased. |

### Pricing

Pay per result: **$0.90 per 1,000 results** ($0.0009 per result). You only pay for results the Actor returns. Set a maximum total charge on the run to cap your spend.

### Limits

- Follows HTTP redirects only (status 3xx with `Location`). Meta-refresh and JavaScript redirects are not followed.
- Up to 30 hops per URL (`maxRedirects`, default 10). Loops and over-long chains are reported as rows.
- Unreachable URLs (DNS failure, refused connection, timeout, TLS error) produce no result and cost nothing; the run log names the reason. If no URL can be checked, the run fails with zero results.
- Checks what is publicly served. Headers carrying secrets (Authorization, API keys, tokens) are not sent.
- At most 5 URLs in parallel and at most one request per second to the same host.
- HEAD responses do not always show compression; use GET for that check.
- Internationalised domain names (for example `münchen.de`) are converted to their ASCII form before the request.

### FAQ

**How much does it cost?** $0.90 per 1,000 checked URLs. Unreachable URLs are free.

**Is the score the same as other header graders?** No. It is this Actor's own weighting, documented in the Scoring table, so every point can be traced to a header value.

**Why do HEAD and GET give different results?** Some servers or CDNs answer HEAD with different headers or status codes, and many only report compression on GET. Switch **Request method** to `GET` to see what a browser gets.

**Why is a URL missing from the results?** The domain did not resolve, the connection failed or timed out, or the certificate was invalid. The run log names the reason for each skipped URL.

**Can I check URLs from another run?** Yes. Set **Read URLs from a dataset** to that run's dataset ID and **Dataset URL field** to the field holding the URL.

**How do I get a spreadsheet?** Set **Output format** to `flat` and export the dataset as CSV or Excel.

**Need DNS records, TLS certificate expiry or indexability?** See Plain Pipe's DNS Records Lookup, Website Status Checker and Indexability Checker. For on-page tags, see Plain Pipe's SEO Page Audit & On-Page Checker.

**Can I monitor headers on a schedule?** Yes. Use Apify Schedules for recurring runs and the Apify API, webhooks or integrations to compare `securityScore` or `issues` over time.

### Why this one

- $0.90 per 1,000 results ($0.0009 per checked URL); unreachable URLs are not charged.
- Each row gives the value to set for every weak or missing header and the points it adds, plus parsed CSP (unsafe-inline, unsafe-eval, missing directives) and HSTS (max-age, includeSubDomains, preload readiness).
- Redirect chain with per-hop timing and loop detection, CORS, cache, compression, HTTP/2 and HTTP/3 checks in the same row; `flat` output for spreadsheets.
- HEAD requests by default with automatic GET fallback, 5 URLs in parallel; no browser and no proxy. The 2-URL prefill run finishes in under 5 seconds (about 2 s in our tests), and the prefilled input is test-run daily.

### Legal and data

This Actor processes only what you give it or public, non-personal technical data. It does not log in anywhere, does not collect personal data, and does not bypass paywalls, CAPTCHAs or access controls. You are responsible for having the right to process the inputs you provide.

### Support

Open an issue on the Issues tab. Issues are answered within 14 days.

Built and maintained by Plain Pipe.

# Actor input Schema

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

URLs to check, one per line, e.g. http://example.com/old-page. A bare domain such as example.com is read as https://example.com; start with http:// to test the HTTP to HTTPS redirect. Invalid entries are skipped with a log warning. Can be combined with a dataset below.

## `datasetId` (type: `string`):

ID or name of an Apify dataset whose items hold URLs, e.g. the output of a sitemap or crawler run ("aBcD1234efGh5678"). Items are read up to Max results. Leave empty to use only the URLs list.

## `datasetUrlField` (type: `string`):

Name of the field that holds the URL in each dataset item, e.g. url or loc. Default url.

## `method` (type: `string`):

HEAD (default) asks only for headers and is lighter. GET requests the full response like a browser, which some servers answer differently (for example compression is often only reported on GET). If a server refuses HEAD (405 or 501), that URL is retried with GET automatically.

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

Which client to present as. bot (default) sends a plain checker User-Agent. desktop and mobile send a browser-shaped desktop or Android string (still ending in SiteCheckBot/1.0), so servers that vary by device return that variant. Example: mobile.

## `headers` (type: `object`):

Extra headers to send with every request, as a JSON object, e.g. {"Accept-Language": "de-DE", "X-Debug": "1"}. A User-Agent here overrides the choice above. Headers that carry secrets (Authorization, API keys, tokens) are refused.

## `origin` (type: `string`):

Optional site to send as the Origin request header, e.g. example.org, to see how the URL answers cross-origin requests (Access-Control-Allow-Origin and related headers are analysed in every row).

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

Stop following after this many redirects, e.g. 5. Longer chains are reported with tooManyRedirects true. 0 records only the first response. Default 10.

## `includeHopHeaders` (type: `boolean`):

If true, each hop in redirectChain also carries all its response headers (useful to see where HSTS or caching headers are set). Default false keeps rows small.

## `checkHttp2` (type: `boolean`):

If true (default), opens one TLS handshake to the final HTTPS host to read whether it offers HTTP/2 (ALPN h2) and the TLS version. No extra HTTP request is made. HTTP/3 is read from the Alt-Svc header either way.

## `outputFormat` (type: `string`):

full (default) gives nested objects per URL: every hop, per-header scores, CSP, HSTS, CORS, cache details and all headers. flat gives one level of plain columns (lists joined with " | ") that opens cleanly as CSV or in a spreadsheet.

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

How many URLs to check at the same time, 1 to 5, e.g. 5. Requests to the same host stay at most one per second regardless. Default 5.

## `timeoutSecs` (type: `integer`):

Give up on a request after this many seconds, e.g. 15. A URL that times out is skipped and not charged. Default 15.

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

Check at most this many URLs, e.g. 1000. You are charged per checked URL, so this also caps the cost. Default 100.

## Actor input object example

```json
{
  "urls": [
    "http://apify.com",
    "https://docs.apify.com"
  ],
  "datasetUrlField": "url",
  "method": "HEAD",
  "userAgent": "bot",
  "headers": {},
  "maxRedirects": 10,
  "includeHopHeaders": false,
  "checkHttp2": true,
  "outputFormat": "full",
  "maxConcurrency": 5,
  "timeoutSecs": 15,
  "maxItems": 2
}
```

# Actor output Schema

## `results` (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 = {
    "urls": [
        "http://apify.com",
        "https://docs.apify.com"
    ],
    "headers": {},
    "maxItems": 2
};

// Run the Actor and wait for it to finish
const run = await client.actor("plainpipe/http-headers-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 = {
    "urls": [
        "http://apify.com",
        "https://docs.apify.com",
    ],
    "headers": {},
    "maxItems": 2,
}

# Run the Actor and wait for it to finish
run = client.actor("plainpipe/http-headers-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 '{
  "urls": [
    "http://apify.com",
    "https://docs.apify.com"
  ],
  "headers": {},
  "maxItems": 2
}' |
apify call plainpipe/http-headers-checker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,plainpipe/http-headers-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/tpBxBmYlltOgdMZXS/builds/cNUoiynRgyVStRKgY/openapi.json
