# X (Twitter) Ads Transparency \[$5💰] Archive Scraper (`memo23/x-ads-transparency-scraper`) Actor

Scrape X (Twitter)'s public ad-transparency archives — commercial, US political & issue ads — into structured rows with spend, impressions, targeting, billing and agency. Filter by advertiser, keyword, date or spend. Hydrate commercial tweets into full creatives. No login. JSON, CSV or Excel.

- **URL**: https://apify.com/memo23/x-ads-transparency-scraper.md
- **Developed by:** [Muhamed Didovic](https://apify.com/memo23) (community)
- **Categories:** Social media, AI, Agents
- **Stats:** 4 total users, 3 monthly users, 88.9% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 ad records

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## X (Twitter) Ads Transparency Archive Scraper

Turn X / Twitter's public **Ads Repository** into clean, structured, exportable data. This actor pulls every publicly-published X advertising archive — the **commercial-communications** snapshot plus the **US political-campaigning** and **issue-ads** archives — and returns one tidy row per ad, with spend, impressions, targeting breakdowns, billing details and (optionally) the fully hydrated tweet creative. No login, no API key.

![How it works](https://raw.githubusercontent.com/muhamed-didovic/muhamed-didovic.github.io/main/assets/how-it-works-x-ads.png)

> ⚠️ **Read this first — it's historical transparency data, not a live ad feed.** X does **not** publish a live, current advertising feed anywhere public. What *is* public (and what this actor scrapes) are three frozen archives: the **commercial** archive is a December 2023 snapshot, and the **political** + **issue** archives are frozen at the 2018–2019 political-advertising era (X banned political ads in November 2019). If you need *today's* competitor ads, this is not that tool. If you want a structured, queryable copy of what X has officially disclosed, it's exactly that.

### Why use this actor

- **Nothing else on the Store does it.** There is no dedicated X/Twitter ad-transparency scraper — you'd otherwise be hand-parsing a 1.37 GB CSV and two 40–76 MB JSON blobs yourself.
- **The political & issue data is genuinely rich.** Per-ad **spend in USD**, **impressions**, **targeting breakdowns** (by geography, age bucket, gender, language — each with its own impression count), plus account-level **billing** (company, city/state, agency, even the disclosed card-holder name).
- **Full tweet hydration.** The commercial archive only stores tweet IDs; flip on `hydrateTweets` and each ad becomes a complete creative — text, media URLs, author, language, engagement counts and post time.
- **Filter server-side.** By advertiser, keyword, date, minimum spend or minimum impressions — so you export only what you need and pay only for matching rows.
- **Robust & cheap to run.** These are static public files on X's CDN — no anti-bot, no browser, no breakage on UI redesigns.

### Overview

X publishes an official Ads Repository to satisfy advertising-transparency obligations. This actor knows where each archive lives and how it's shaped, downloads it, filters it, normalizes every ad into a single consistent schema, and pushes one row per promoted tweet to your dataset. You pick the archive(s), set your filters, and (for commercial ads) decide whether to hydrate the underlying tweets.

### Supported inputs

| Source (`sources`) | What it contains | Era | Richness |
|---|---|---|---|
| `political` | US political-campaigning ads | 2018–2019 | **High** — spend, impressions, targeting, billing, agency |
| `issue` | US issue ads (advocacy, cause) | 2018–2019 | **High** — same rich schema |
| `commercial` | Commercial promoted-tweet archive | Dec 2023 | Tweet IDs → **hydratable** to full creatives |

You can select one, two, or all three in a single run.

### Use cases

- **Political-ad research & journalism** — reconstruct 2018–2019 US campaign ad spend, who spent what, where it was targeted, and which agency ran it.
- **Academic & OSINT analysis** — a clean, filterable copy of X's disclosed advertising for datasets, papers and audits.
- **Ad-creative & compliance archives** — snapshot commercial promoted tweets (with `#ad` disclosure), hydrated into full creatives with media and engagement.
- **Advertiser & agency mapping** — see which agencies (e.g. *Bully Pulpit Interactive*, *GPS Impact*) ran which campaigns, and the billing entities behind them.
- **Targeting studies** — analyze how advertisers sliced audiences by geography, age, gender and language, with per-segment impression counts.

### How it works

1. You choose `sources` and optional filters.
2. For **political/issue**, the actor downloads the archive JSON, parses it, and emits one row per ad, denormalizing account + billing fields onto every row.
3. For **commercial**, the actor *streams* the 1.37 GB CSV line-by-line (never loading it into memory), matching rows on the fly and stopping as soon as your item cap is met. With `hydrateTweets`, each matched ad's tweet is fetched from X's public syndication endpoint and enriched.
4. Every ad is charged and pushed to your dataset in a single, consistent schema.

### Input configuration

| Field | Type | Default | Description |
|---|---|---|---|
| `sources` | array | `["political"]` | Which archives to scrape: `political`, `issue`, `commercial`. |
| `advertisers` | array | `[]` | Filter to advertisers (matches handle **and** account name, case-insensitive). |
| `search` | string | `""` | Keyword filter across tweet text, account name, handle, reported URLs. |
| `startDate` / `endDate` | string | `""` | Keep ads within a `YYYY-MM-DD` date range. |
| `minSpend` | integer | — | *(political/issue)* minimum total ad spend in USD. |
| `minImpressions` | integer | — | *(political/issue)* minimum total impressions. |
| `hydrateTweets` | boolean | `false` | *(commercial)* fetch each tweet's full creative + engagement. |
| `liveCheck` | boolean | `false` | Best-effort live promoted-tweet lookup (almost always empty — see FAQ). |
| `maxItems` | integer | `1000` | Hard cap on output rows across all sources. |
| `maxConcurrency` | integer | `10` | Parallelism for hydration / live check. |
| `proxy` | object | none | Optional proxy (rarely needed; helps for bulk hydration). |

#### Example inputs

Rich political ads over $500 spend, from EMILY's List:
```json
{ "sources": ["political"], "advertisers": ["emilyslist"], "minSpend": 500, "maxItems": 100 }
````

Commercial ads for one advertiser, hydrated to full creatives:

```json
{ "sources": ["commercial"], "advertisers": ["anemone_tar"], "hydrateTweets": true, "maxItems": 50 }
```

Everything an advertiser disclosed, political + issue:

```json
{ "sources": ["political", "issue"], "search": "climate", "maxItems": 500 }
```

### Output overview

One row per ad (promoted tweet). Sample **political** row (trimmed):

```json
{
  "source": "political",
  "adType": "political-campaigning",
  "advertiserHandle": "emilyslist",
  "advertiserName": "@emilyslist - U.S. Political Campaigning - Bully Pulpit Interactive",
  "advertisingAgency": "Bully Pulpit Interactive",
  "tweetId": "1153761056323440641",
  "tweetUrl": "https://twitter.com/transparency/status/1153761056323440641",
  "createdAt": "2019-07-23",
  "tweetText": "We're witnessing a coordinated attack on women's rights…",
  "totalSpend": 8.89,
  "totalImpressions": 3873,
  "campaigns": [
    { "startDate": "2019-07-23 18:30:29 +0000", "endDate": "2019-08-01 03:59:00 +0000",
      "spend": 366.19, "impressions": 45241, "numberTweets": 1,
      "targeting": [ { "target": "Missouri- US", "targetType": "GEO", "impressions": 775 } ] }
  ],
  "targeting": [ { "target": "40-49", "targetType": "AGE_BUCKET", "impressions": 8230 } ],
  "insertionOrders": [ { "companyName": "Cory 2020", "soldTo": "Cory 2020",
    "spend": 4944.61, "billingCity": "Newark", "billingState": "NJ", "billingPostalCode": "07102" } ],
  "creditCardBilling": []
}
```

Sample **commercial** row with `hydrateTweets` on (trimmed):

```json
{
  "source": "commercial",
  "adType": "commercial",
  "advertiserHandle": "myhomedreamer",
  "tweetId": "1734460233865658510",
  "tweetUrl": "https://www.x.com/myhomedreamer/status/1734460233865658510",
  "createdAt": "2023-12-12",
  "tweetText": "https://t.co/VGn5DCf32n\n#ad",
  "hydration": {
    "hydrated": true,
    "authorName": "🏠まほ", "authorHandle": "myhomedreamer",
    "tweetCreatedAt": "2023-12-12T06:28:39.000Z", "lang": "qme",
    "likeCount": 1, "replyCount": 0, "mediaUrls": []
  }
}
```

### Key output fields

- `source` / `adType` — which archive and ad category.
- `advertiserHandle` / `advertiserName` / `advertisingAgency` — the advertiser and the agency that ran it.
- `tweetId` / `tweetUrl` / `createdAt` — the promoted tweet and its date.
- `tweetText` / `reportedUrls` — creative copy and landing/reported links.
- `totalSpend` / `totalImpressions` — headline metrics *(political/issue)*.
- `campaigns[]` — per-campaign start/end, spend, impressions and full `targeting[]`.
- `targeting[]` — flattened targeting across all campaigns (`GEO` / `AGE_BUCKET` / `GENDER` / `LANGUAGE`, each with impressions).
- `insertionOrders[]` / `creditCardBilling[]` — disclosed billing entities *(political/issue)*.
- `hydration` — full tweet creative + engagement *(commercial, when enabled)*.

### FAQ

**Is this live / current ad data?** No. See the warning at the top. The commercial archive is frozen at December 2023; political and issue are frozen at 2018–2019. X publishes no public live ad feed.

**Why is `liveCheck` almost always empty?** X's live promoted-tweets endpoint only returns *currently in-flight* ads. Political ads are banned, and the commercial live surface returns nothing for essentially every advertiser we tested (major brands, EU institutions, news outlets). It's included for completeness and future-proofing, off by default.

**Why can a commercial advertiser filter take a while?** The 1.37 GB CSV isn't sorted by advertiser, so a *complete* per-advertiser sweep must stream the whole file. Progress is logged, and if a scan cap truncates results the run warns you (results are never silently partial). Runs with no filter, or with a generous item cap, finish quickly.

**Do deleted tweets hydrate?** No — deleted, suspended or protected tweets return `hydration.hydrated: false` with a short reason, but the archive row (ID, URL, date) is still included.

**Which regions does the political/issue data cover?** Primarily US political-campaigning and US issue ads, with a small number of other-country political entries (e.g. IN). Targeting is US-DMA-level for geography.

### Support

Found a bug or want another archive/field supported? Open an issue on the actor's **Issues** tab in Apify Console and we'll take a look.

### Additional services

Need a custom scraper for another site, or enrichment (contact emails, company data) bolted onto these results? Get in touch — custom builds welcome.

### Explore more scrapers

Browse the full catalog of 290+ production scrapers: [muhamed-didovic.github.io](https://muhamed-didovic.github.io)

### ⚠️ Disclaimer

This actor collects **only publicly available data** that X (Twitter) itself publishes in its official Ads Repository for advertising-transparency purposes — no login, no authentication, no private or personal data beyond what X has chosen to disclose publicly. It does not bypass any access control. The data is provided **as published by X** and is historical (see the dating notes above); accuracy, completeness and availability depend entirely on X's published archives and may change or be withdrawn by X at any time. Use of the data must comply with X's Terms of Service and all applicable laws, including data-protection and electoral-transparency regulations in your jurisdiction. You are responsible for how you use the output. This actor is an independent tool and is not affiliated with, endorsed by, or sponsored by X Corp. or Twitter.

### SEO Keywords

X ads scraper, Twitter ads scraper, X ad transparency, Twitter ad transparency, X ads repository, Twitter ads repository, political ads scraper, issue ads scraper, ad spend data, ad impressions data, ad targeting data, promoted tweets scraper, Twitter ad library, X ad library, ad transparency archive, campaign ad spend, advertising transparency, Twitter political advertising, X commercial communications, ad billing data, Apify Twitter scraper, Apify X scraper.

# Actor input Schema

## `sources` (type: `array`):

One or more of: political (US Political Campaigning ads), issue (US Issue ads), commercial (commercial communications / promoted tweets). Defaults to political.

## `advertisers` (type: `array`):

Filter to specific advertisers. Case-insensitive; matches the account handle AND the full account name. e.g. \["emilyslist", "Cory 2020"] for political, or \["anemone\_tar"] for commercial. For the commercial archive, note the CSV isn't sorted by advertiser, so an advertiser filter streams the whole 1.37 GB file.

## `search` (type: `string`):

Free-text filter. Case-insensitive; matches tweet text, account name, handle and reported/landing URLs.

## `startDate` (type: `string`):

Only keep ads dated on/after this date. Commercial uses the creative's recorded date; political/issue use the earliest campaign start date.

## `endDate` (type: `string`):

Only keep ads dated on/before this date.

## `minSpend` (type: `integer`):

political/issue only: keep ads whose total spend is at least this many US dollars.

## `minImpressions` (type: `integer`):

political/issue only: keep ads with at least this many total impressions.

## `hydrateTweets` (type: `boolean`):

Commercial archive only. For each ad, fetch the public tweet via X's syndication endpoint and add tweetText, mediaUrls, authorName/Handle, like/reply counts, language and creation time. Adds network calls and time; deleted/suspended tweets come back un-hydrated. No extra charge.

## `liveCheck` (type: `boolean`):

Best-effort: resolve each advertiser in the Advertisers filter and query X's live promoted-tweets endpoint. In practice this returns nothing for essentially every advertiser (political ads are banned; the commercial live surface is empty), so it's off by default and included only for completeness.

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

Hard cap on output rows across all selected sources. One row = one ad (promoted tweet).

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

Parallel requests when hydrating commercial tweets or running the live check.

## `proxy` (type: `object`):

Optional. The archives are plain public CDN files and rarely need a proxy, but hydrating many commercial tweets can benefit from a residential pool.

## Actor input object example

```json
{
  "sources": [
    "political"
  ],
  "advertisers": [],
  "hydrateTweets": false,
  "liveCheck": false,
  "maxItems": 1000,
  "maxConcurrency": 10,
  "proxy": {
    "useApifyProxy": 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 = {
    "sources": [
        "political"
    ],
    "advertisers": [],
    "search": "",
    "startDate": "",
    "endDate": "",
    "proxy": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("memo23/x-ads-transparency-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 = {
    "sources": ["political"],
    "advertisers": [],
    "search": "",
    "startDate": "",
    "endDate": "",
    "proxy": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("memo23/x-ads-transparency-scraper").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "sources": [
    "political"
  ],
  "advertisers": [],
  "search": "",
  "startDate": "",
  "endDate": "",
  "proxy": {
    "useApifyProxy": false
  }
}' |
apify call memo23/x-ads-transparency-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=memo23/x-ads-transparency-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "X (Twitter) Ads Transparency [$5💰] Archive Scraper",
        "description": "Scrape X (Twitter)'s public ad-transparency archives — commercial, US political & issue ads — into structured rows with spend, impressions, targeting, billing and agency. Filter by advertiser, keyword, date or spend. Hydrate commercial tweets into full creatives. No login. JSON, CSV or Excel.",
        "version": "0.0",
        "x-build-id": "R9ZgpDBOKUgGrB9n2"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/memo23~x-ads-transparency-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-memo23-x-ads-transparency-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/memo23~x-ads-transparency-scraper/runs": {
            "post": {
                "operationId": "runs-sync-memo23-x-ads-transparency-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/memo23~x-ads-transparency-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-memo23-x-ads-transparency-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "sources": {
                        "title": "Ad archives to scrape",
                        "type": "array",
                        "description": "One or more of: political (US Political Campaigning ads), issue (US Issue ads), commercial (commercial communications / promoted tweets). Defaults to political.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "political",
                                "issue",
                                "commercial"
                            ],
                            "enumTitles": [
                                "Political — US political-campaigning ads (spend + targeting + billing)",
                                "Issue — US issue ads (spend + targeting + billing)",
                                "Commercial — promoted-tweet archive (Dec 2023, hydratable)"
                            ]
                        },
                        "default": [
                            "political"
                        ]
                    },
                    "advertisers": {
                        "title": "Advertisers",
                        "type": "array",
                        "description": "Filter to specific advertisers. Case-insensitive; matches the account handle AND the full account name. e.g. [\"emilyslist\", \"Cory 2020\"] for political, or [\"anemone_tar\"] for commercial. For the commercial archive, note the CSV isn't sorted by advertiser, so an advertiser filter streams the whole 1.37 GB file.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "search": {
                        "title": "Keyword search",
                        "type": "string",
                        "description": "Free-text filter. Case-insensitive; matches tweet text, account name, handle and reported/landing URLs."
                    },
                    "startDate": {
                        "title": "Start date (YYYY-MM-DD)",
                        "type": "string",
                        "description": "Only keep ads dated on/after this date. Commercial uses the creative's recorded date; political/issue use the earliest campaign start date."
                    },
                    "endDate": {
                        "title": "End date (YYYY-MM-DD)",
                        "type": "string",
                        "description": "Only keep ads dated on/before this date."
                    },
                    "minSpend": {
                        "title": "Minimum spend (USD)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "political/issue only: keep ads whose total spend is at least this many US dollars."
                    },
                    "minImpressions": {
                        "title": "Minimum impressions",
                        "minimum": 0,
                        "type": "integer",
                        "description": "political/issue only: keep ads with at least this many total impressions."
                    },
                    "hydrateTweets": {
                        "title": "Hydrate commercial tweets (adds text, media, author, engagement)",
                        "type": "boolean",
                        "description": "Commercial archive only. For each ad, fetch the public tweet via X's syndication endpoint and add tweetText, mediaUrls, authorName/Handle, like/reply counts, language and creation time. Adds network calls and time; deleted/suspended tweets come back un-hydrated. No extra charge.",
                        "default": false
                    },
                    "liveCheck": {
                        "title": "Also check for LIVE promoted tweets (usually empty)",
                        "type": "boolean",
                        "description": "Best-effort: resolve each advertiser in the Advertisers filter and query X's live promoted-tweets endpoint. In practice this returns nothing for essentially every advertiser (political ads are banned; the commercial live surface is empty), so it's off by default and included only for completeness.",
                        "default": false
                    },
                    "maxItems": {
                        "title": "Maximum ad records",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Hard cap on output rows across all selected sources. One row = one ad (promoted tweet).",
                        "default": 1000
                    },
                    "maxConcurrency": {
                        "title": "Max concurrency (hydration / live check)",
                        "minimum": 1,
                        "maximum": 20,
                        "type": "integer",
                        "description": "Parallel requests when hydrating commercial tweets or running the live check.",
                        "default": 10
                    },
                    "proxy": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Optional. The archives are plain public CDN files and rarely need a proxy, but hydrating many commercial tweets can benefit from a residential pool.",
                        "default": {
                            "useApifyProxy": false
                        }
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
