# Threads Scraper (`reportable_broth/threads-scraper-monitor`) Actor

Threads scraper with no login. Search any keyword or extract a profile's posts, replies, reposts and media. Returns text, author, engagement counts, timestamps and media URLs. Export JSON, CSV or Excel. Only-new mode for scheduled monitoring. $1.99 per 1,000 posts.

- **URL**: https://apify.com/reportable\_broth/threads-scraper-monitor.md
- **Developed by:** [Quiet Harvest](https://apify.com/reportable_broth) (community)
- **Categories:** Social media, Automation, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.99 / 1,000 post 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

## Threads Scraper — Keyword Monitor & Profile History | $1.99 / 1K posts | No Login

Scrape **Meta Threads (threads.com)** without logging in. No cookies, no account pool, no session to get banned — this Actor reads only public pages.

**$1.99 per 1,000 posts returned. Platform usage included — no second bill for compute or proxy.**

***

### What you can do with it

**Six modes, one Actor:**

| # | Mode | What you get |
|---|---|---|
| 1 | **Keyword / hashtag search** | The freshest public posts for each keyword, on a schedule, with only-new filtering |
| 2 | **Profile history** | An account's posts paginated back through time, months deep |
| 3 | **Replies** | The replies that account wrote |
| 4 | **Reposts** | What that account reposted |
| 5 | **Media** | That account's posts that carry an image or video |
| 6 | **Find accounts** | Who is talking about your keyword, ranked by matching posts and engagement |

Mix any of them in a single run. Every item is tagged so you can split them downstream.

- **Brand and mention monitoring** — catch posts about your product minutes after they go live
- **Social listening and PR** — spot a complaint or a viral thread early
- **Competitor analysis** — pull a rival's full post history with engagement numbers
- **Lead and creator discovery** — collect authors who post about your niche
- **AI agents and RAG** — clean, structured, timestamped text ready to embed
- **Trend research** — gather a topic or hashtag over weeks and analyse it downstream

***

### Why this one

Most Threads scrapers need a logged-in session or a pool of burner accounts. That is where they break: accounts get flagged, sessions expire, and your scheduled run fails at 3am.

| | This Actor | Typical Threads scraper |
|---|---|---|
| Login required | **No** | Yes — session or account pool |
| Ban / rate-limit risk | **None — no credential exists** | Accounts get flagged |
| Only-new mode for schedules | **Built in** | Usually dedupe it yourself |
| Keyword monitoring | **Yes, recent sort** | Often relevance only |
| Full profile history | **Yes, months back** | Often first page only |
| Platform usage cost | **Included in the price** | Sometimes billed on top |

***

### Choose your workflow

#### Mode 1 — Monitor keywords, hashtags and brand names

Fill in `keywords`. Each keyword is searched in each mode you list under `modes`.

```json
{
  "keywords": ["your brand", "competitor brand"],
  "modes": ["recent"],
  "onlyNew": true
}
```

`recent` returns the newest public posts, which is what you want for monitoring — posts show up seconds after they are published. Put this on a schedule and every run hands you only what appeared since last time.

#### Mode 2 — Scrape the full public history of a profile

Fill in `usernames`. The Actor pages backwards through the profile until it hits your cap.

```json
{
  "usernames": ["nike", "adidas"],
  "maxPostsPerProfile": 300,
  "onlyNew": false
}
```

Set `onlyNew` to `false` for a one-off history pull, otherwise a second run will look empty — that is the dedupe doing its job.

#### Mode 3, 4, 5 — Replies, reposts and media

Add `profileTabs` alongside `usernames` to pull an account's other tabs.

```json
{
  "usernames": ["nike"],
  "profileTabs": ["replies", "reposts", "media"]
}
```

Each item is tagged with `_mode` = `replies`, `reposts` or `media`.

Two things worth knowing up front:

- **These tabs return one page** (typically 5 to 20 items). That is a Threads limit for anonymous access — those tabs hand out no pagination cursor at all. The main posts tab is unaffected and still goes back months.
- **An empty tab is normal, not an error.** Plenty of brand accounts never repost, and many never reply publicly. The Actor reports what is actually there rather than inventing results.

#### Mode 6 — Find the accounts talking about your keyword

Turn on `findAccounts` with your keywords.

```json
{
  "keywords": ["korean skincare"],
  "modes": ["recent", "top"],
  "findAccounts": true
}
```

You get account records (`_source` = `account`) alongside the posts, ranked by how many matching posts each author has and their total engagement — a ready-made shortlist of creators and prospects in your niche.

**These account records are not charged separately.** They are aggregated from posts you already paid for.

#### Everything in one run

```json
{
  "keywords": ["running shoes"],
  "usernames": ["nike"],
  "profileTabs": ["replies", "media"],
  "modes": ["recent", "top"],
  "findAccounts": true,
  "maxPostsPerProfile": 100
}
```

Every item carries `_source` (`search`, `profile` or `account`) and `_mode` so you can split them downstream.

***

### Ready-made examples

**Brand monitoring, every 15 minutes**

```json
{
  "keywords": ["acme corp", "acmecorp", "#acme"],
  "modes": ["recent"],
  "onlyNew": true,
  "maxAgeHours": 24
}
```

**Competitor back-catalogue, one-off**

```json
{
  "usernames": ["competitor_handle"],
  "maxPostsPerProfile": 1000,
  "onlyNew": false
}
```

**Hashtag campaign tracking**

```json
{
  "keywords": ["#summersale2026"],
  "modes": ["tags", "recent"],
  "onlyNew": true
}
```

**Topic research, widest net**

```json
{
  "keywords": ["electric vehicle", "EV charging"],
  "modes": ["recent", "top", "tags"],
  "onlyNew": false
}
```

**Creator discovery in a niche**

```json
{
  "keywords": ["skincare routine", "korean skincare"],
  "modes": ["top"],
  "onlyNew": true
}
```

**Feed an AI agent fresh posts on demand**

```json
{
  "keywords": ["the topic your agent is asking about"],
  "modes": ["recent"],
  "onlyNew": false,
  "maxAgeHours": 6
}
```

***

***

### Working in more than one language

Most keywords are used by people writing in several languages at once, and Threads
mixes them together. Two controls handle that.

**On the way in — `searchLanguage`.** Pick the language your results should lean
towards. Threads decides this from the request's language preference, so this is a
genuine bias on the result set, not a post-hoc filter:

```json
{
  "keywords": ["skincare"],
  "searchLanguage": "ko",
  "modes": ["recent"]
}
```

Nineteen options: English, Traditional and Simplified Chinese, Japanese, Korean,
Thai, Vietnamese, Indonesian, Malay, Filipino, Spanish, Portuguese, French, German,
Italian, Arabic, Russian, Turkish, Hindi. It is a preference — a keyword only one language uses will
return that language whichever option you pick.

**On the way out — `language`.** Every post carries the language its text was written
in, so you can route, filter or alert per language downstream:

```python
korean = [p for p in items if p["language"] == "ko"]
```

**How the detection works, and where it stops.** Scripts that are unambiguous —
Hangul, kana, Thai, Arabic, Hebrew, Cyrillic, Devanagari, Greek — are read directly
from the characters, which makes them reliable. Vietnamese is identified by its
diacritics. The remaining Latin-script languages (English, Spanish, Portuguese,
French, German, Italian, Indonesian, Malay, Filipino, Turkish) are scored on
common function words.

Two honest limits:

- **A post with too little text returns `null`.** One word, a bare URL or only emoji
  cannot be classified, and a guess would be worse than a blank.
- **Malay and Indonesian share most of their function words.** When a post uses only
  words common to both, it is reported as `id`. Posts carrying a marker specific to
  one of them (`tak`, `boleh`, `sis` for Malay; `gak`, `banget`, `bisa` for
  Indonesian) are separated correctly.
- **Japanese written entirely in kanji, with no kana, is reported as `zh`.** Those
  characters are genuinely shared between the two languages; nothing in the text
  distinguishes them.

### Input reference

| Field | Type | Default | What it does |
|---|---|---|---|
| `keywords` | array | — | Keywords or hashtags to search. Each returns up to about 20 posts per mode. |
| `usernames` | array | — | Accounts to scrape in full, with or without the @ sign. |
| `profileTabs` | array | `[]` | Extra tabs to pull for each account: `replies`, `reposts`, `media`. |
| `findAccounts` | boolean | `false` | Also return the accounts talking about your keywords. Not charged separately. |
| `modes` | array | `["recent"]` | `recent` = newest first, best for monitoring. `top` = relevance. `tags` = hashtag search. |
| `searchLanguage` | string | `en` | Which language results should lean towards. 17 options. A preference, not a hard filter. |
| `maxPostsPerProfile` | integer | `100` | Cap per profile in username mode. |
| `onlyNew` | boolean | `true` | Return only posts not seen in previous runs with the same keywords. 7-day memory. |
| `maxAgeHours` | integer | `0` | Drop posts older than this many hours. `0` means no limit. |
| `proxyConfiguration` | object | Apify residential | Residential recommended. Pages are tiny so proxy cost is minimal. |
| `concurrency` | integer | `4` | Parallel requests. Raise carefully. |

***

### Output

One dataset item per post. Export as JSON, CSV, Excel or XML, or pull it from the Apify API.

| Field | Type | Notes |
|---|---|---|
| `id` | string | Threads internal post id |
| `code` | string | Short code used in the post URL |
| `url` | string | Direct link to the post |
| `text` | string | Post body |
| `language` | string or null | Detected language of the post text, ISO 639-1. `null` when it cannot be determined — see below. |
| `hashtags` | array | Hashtags in the post text, without the `#`. |
| `mentions` | array | Accounts mentioned, read from Threads' own text fragments where available and parsed from the text otherwise. |
| `urls` | array | Links in the post text. |
| `topic_tag` | string or null | The topic Threads filed the post under, e.g. `Food Threads`. |
| `published_at` | string | ISO 8601 UTC timestamp |
| `published_ts` | integer | The same moment as a Unix timestamp |
| `media_type` | string | text, image, video or carousel |
| `media` | array | Media URLs with width and height |
| `like_count` | integer | |
| `reply_count` | integer | |
| `repost_count` | integer | |
| `quote_count` | integer | |
| `is_reply` | boolean | Whether the post is itself a reply |
| `user` | object | username, full\_name, is\_verified, profile\_pic\_url |
| `_source` | string | `search`, `profile` or `account` |
| `_query` | string | Which keyword or username produced this item |
| `_mode` | string | `recent`, `top`, `tags`, `profile`, `replies`, `reposts` or `media` |

#### Account record (when `findAccounts` is on)

Items with `_source` = `account` have this shape instead:

| Field | Type | Notes |
|---|---|---|
| `username` | string | |
| `full_name` | string | |
| `is_verified` | boolean | |
| `profile_url` | string | Link to the profile |
| `profile_pic_url` | string | |
| `posts_found` | integer | How many matching posts this account had in this run |
| `total_likes` | integer | Summed across those posts |
| `total_replies` | integer | Summed across those posts |
| `sample_post_url` | string | One of their matching posts |
| `_query` | string | The keyword they matched |

#### Sample record

```json
{
  "id": "3988758633525726084",
  "code": "Dda6tgGEsuE",
  "url": "https://www.threads.com/@example/post/Dda6tgGEsuE",
  "text": "...",
  "language": "ko",
  "published_at": "2026-09-18T07:38:24+00:00",
  "media_type": "carousel",
  "media": [{ "type": "image", "url": "https://...", "width": 1080, "height": 1350 }],
  "like_count": 13,
  "reply_count": 19,
  "repost_count": 0,
  "quote_count": 0,
  "is_reply": false,
  "user": {
    "username": "example",
    "full_name": "...",
    "is_verified": false,
    "profile_pic_url": "https://..."
  },
  "_source": "search",
  "_query": "keyword",
  "_mode": "recent"
}
```

***

### Turn it into a live monitor

1. Run the Actor once with your keywords and check the output.
2. Save it as a Task.
3. Add a Schedule — every 5 or 15 minutes works well.
4. Keep `onlyNew` on, so each run emits only posts you have not seen.
5. Connect the dataset to Slack, a webhook, Google Sheets, Make or Zapier.

You now have a Threads mentions feed that never repeats itself.

### Use it from an AI agent

The Actor is callable from the Apify API and over MCP, so an agent can ask for fresh Threads posts on any topic and get structured JSON back — no browser, no login flow, no captcha handling. Set `onlyNew` to `false` for agent calls, so each question gets a full answer rather than a delta.

***

### What to expect

**Keyword search depth.** Threads shows roughly the first 20 public posts per keyword, per sort mode, to anonymous visitors. That is a platform limit, not a bug in this Actor. The design answer is time: run it on a schedule with `onlyNew` and you accumulate continuously. For bulk history, use `usernames` mode, which does paginate.

**Profile depth.** Anonymous pagination walks a profile back through time. On a large, active account this has reached over a year of history in testing. Small accounts simply have less to return.

**Why a run can return few or zero items.** In order of likelihood:

1. `onlyNew` is on and nothing new has appeared since the last run. This is correct behaviour, not a failure.
2. `maxAgeHours` is set and everything found is older than the cutoff.
3. The keyword is genuinely quiet on Threads.
4. The profile is private, deleted, or has no public posts.

**Freshness.** With `recent`, posts appear seconds after publication.

**Public only.** Private and restricted posts are not accessible. This Actor does not attempt to reach them.

***

### FAQ

**Do I need a Threads or Instagram account?**
No. The Actor reads public pages only. There is no login step and no credential to store.

**Can my account get banned?**
There is no account involved, so there is nothing to ban. That is the main reason to use this one.

**Do I need to supply cookies or a session token?**
No. Nothing to paste, nothing to refresh, nothing to expire.

**How many posts does a keyword search return?**
Roughly the first 20 public posts per keyword, per sort mode. See *What to expect* above for why, and what to do about it.

**How far back can it go on a profile?**
Months, and over a year on large accounts in testing. Use `maxPostsPerProfile` to control how deep.

**How fresh are the results?**
With `recent` sort, posts show up seconds after they are published.

**What does it cost?**
$1.99 per 1,000 posts returned. Platform usage is included, so you are not billed separately for compute or proxy.

**Am I charged for duplicate posts?**
No. With `onlyNew` on, posts you already received are filtered before they reach the dataset, so they are never charged.

**My second run returned almost nothing. Is it broken?**
Almost certainly not — that is `onlyNew` working. Set it to `false` if you want the full set every time.

**Can I scrape private accounts?**
No. Public content only.

**Which proxy should I use?**
Residential is recommended and is the default. Pages are about 2.4 KB per post over the wire, so proxy consumption is small.

**Can I use my own proxies?**
Yes, through `proxyConfiguration`.

**Can I filter by date?**
Use `maxAgeHours` to drop anything older than N hours. In profile mode, `maxPostsPerProfile` bounds how far back you go.

**Does it get replies and reposts?**
Posts carry `reply_count`, `repost_count` and `quote_count`, and `is_reply` tells you whether an item is itself a reply.

**A reposts or replies tab came back empty. Is that a bug?**
No. Many accounts simply never repost, and plenty never reply publicly. The Actor reports what is actually on the tab rather than inventing results.

**How deep do the replies / reposts / media tabs go?**
One page, typically 5 to 20 items. This is a Threads limit, not an Actor limit: those tabs report `has_next_page: false` with no cursor to anonymous visitors, so there is no second page to fetch. The main posts tab is different — it does paginate, and `maxPostsPerProfile` takes it back months.

**Are the account records charged?**
No. They are aggregated from posts that were already charged in the same run, so you are not billed twice for the same data.

**Can I run it on a schedule?**
Yes — that is what it is built for. See *Turn it into a live monitor*.

**Does it work with AI agents and MCP?**
Yes. See *Use it from an AI agent*.

***

### Changelog

- **0.2.1** — Lower default memory (runs cost less and you can run more of them in parallel). Clearer warning when profile tabs are selected without any usernames.
- **0.2.0** — Four new modes: profile **replies**, **reposts** and **media** tabs, plus **find accounts** (who is talking about your keyword). Keyword and profile fetches now rotate the proxy and retry when a page comes back empty, instead of silently returning nothing.
- **0.1.9** — Added Actor output schema. No change to scraping behaviour or output fields.
- **0.1.6** — Expanded documentation.
- **0.1.2** — Fixed template resolution when running in the cloud container.
- **0.1.1** — First public build: keyword monitoring, profile history, cross-run dedupe.

***

### Notes and limits

- Reads **public** content only. Private or restricted posts are not accessible.
- Keyword search returns the first page of about 20 posts per sort. Built for monitoring fresh posts over time, not one-shot bulk keyword history. For bulk, use username mode.
- Results reflect what Threads shows publicly at the time of the run.
- Threads changes its public pages from time to time. This Actor is maintained against those changes. Run a small sample first, check the output, then scale up.

***

### Our other Actors

- **[YouTube Monitor](https://apify.com/reportable_broth/youtube-scraper-monitor)** — watch keywords and channels for **new** videos only. Shorts included, exact publish times, like counts, and dedupe across runs so you are never charged twice for the same video.
- **[YouTube Transcript Scraper](https://apify.com/reportable_broth/youtube-transcript-scraper)** — the spoken transcript of any video, by URL, channel or keyword. Falls back to any available language instead of failing.

### Disclaimer

This Actor collects only publicly available data. You are responsible for how you use the data you collect, including compliance with the Threads terms of service, applicable data protection law such as GDPR, and any restrictions that apply in your jurisdiction. If you are unsure, take legal advice before scraping personal data at scale.

***

**Keywords:** threads scraper, threads.com scraper, Meta Threads API, Threads keyword search, Threads hashtag scraper, Threads profile scraper, Threads post history, Threads monitoring, social listening, brand monitoring, no login scraper, Threads data extraction.

# Actor input Schema

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

Keywords or #hashtags to search on Threads. Each = up to ~20 freshest public posts per sort mode. Leave empty if you only want profiles.

## `usernames` (type: `array`):

Threads usernames (with or without @) to scrape ALL public posts from, paginating through history. No login needed.

## `maxPostsPerProfile` (type: `integer`):

Stop paginating a profile after this many posts. Each post is charged once.

## `profileTabs` (type: `array`):

Extra tabs to pull for each account in Usernames. Replies = posts this account wrote as replies. Reposts = what this account reposted. Media = their posts with images or video. Anonymous access returns the first page of each tab. An empty result is normal for accounts that simply do not repost or reply publicly.

## `modes` (type: `array`):

recent = newest posts (best for monitoring). top = Threads' relevance ranking. tags = hashtag search.

## `searchLanguage` (type: `string`):

Which language the results should lean towards. Many keywords are used by people writing in several languages and Threads mixes them together; picking a language here biases the result set towards it.

This is a preference, not a hard filter — a keyword only one language uses will return that language whatever you pick. Every post also carries a detected `language` field in the output, which you can filter on.

## `findAccounts` (type: `boolean`):

Adds account records to the dataset, aggregated from the posts found: who posts about your keywords, how many matching posts each has, and their total engagement. Useful for finding creators, KOLs and prospects. These records are NOT charged separately - they are a summary of posts you already paid for. Look for items with \_source = account.

## `onlyNew` (type: `boolean`):

Keeps a per-task memory of post IDs (7 days). Turn on for scheduled monitoring so every run yields only NEW posts. Turn off to always get the full ~20 per keyword.

## `maxAgeHours` (type: `integer`):

Drop posts older than this. 0 = no limit.

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

Residential proxy recommended. Anonymous Threads pages are light (~50 KB per 20 posts), so proxy cost is negligible.

## `concurrency` (type: `integer`):

Parallel requests.

## Actor input object example

```json
{
  "keywords": [
    "台北",
    "iPhone 17"
  ],
  "usernames": [
    "zuck"
  ],
  "maxPostsPerProfile": 100,
  "profileTabs": [],
  "modes": [
    "recent"
  ],
  "searchLanguage": "en",
  "findAccounts": false,
  "onlyNew": true,
  "maxAgeHours": 0,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "concurrency": 4
}
```

# Actor output Schema

## `posts` (type: `string`):

No description

# API

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

## JavaScript example

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

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

// Prepare Actor input
const input = {
    "keywords": [
        "台北",
        "iPhone 17"
    ],
    "usernames": [
        "zuck"
    ],
    "modes": [
        "recent"
    ],
    "searchLanguage": "en",
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("reportable_broth/threads-scraper-monitor").call(input);

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

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

```

## Python example

```python
from apify_client import ApifyClient

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

# Prepare the Actor input
run_input = {
    "keywords": [
        "台北",
        "iPhone 17",
    ],
    "usernames": ["zuck"],
    "modes": ["recent"],
    "searchLanguage": "en",
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("reportable_broth/threads-scraper-monitor").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "keywords": [
    "台北",
    "iPhone 17"
  ],
  "usernames": [
    "zuck"
  ],
  "modes": [
    "recent"
  ],
  "searchLanguage": "en",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call reportable_broth/threads-scraper-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,reportable_broth/threads-scraper-monitor"
        }
    }
}
```

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/0R8zdvdsnacYuTfxk/builds/NcAs6nc5FdtHknYzE/openapi.json
