# Snapchat Political Ads Scraper: Spend & Targeting (`automation_craft/snapchat-political-ads-scraper`) Actor

Scrape Snap's Political Ads Library, 80,000+ ads from 54 countries since 2018, no login or API key. Get the paying advertiser, organization, candidate or ballot, spend, impressions, dates, targeted regions, ages, interests and a direct media link. JSON, CSV or API; pay per ad delivered.

- **URL**: https://apify.com/automation_craft/snapchat-political-ads-scraper.md
- **Developed by:** [Automation Craft](https://apify.com/automation_craft) (community)
- **Categories:** News, Social media, Marketing
- **Stats:** 4 total users, 3 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.40 / 1,000 political ads

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### Snapchat Political Ads Scraper: Spend & Targeting

Get **Snapchat political ads** from Snap's public Political Ads Library as clean rows: who paid, how much they spent, how many impressions they bought, when the ad ran, and which countries, states, districts, ages and interests it targeted, with a direct link to the media file of every creative.

Snap publishes its Political Ads Library as one file per year, 2018 to 2026, worldwide. On 2026-10-06 the nine files held 80,162 ads from 54 countries in 11 currencies; 58,484 of them (73 percent) are United States ads. This Actor reads those files, applies your filters to each ad and delivers one row per ad. No login and no API key.

- **Every column.** All 38 columns of Snap's file as parsed fields, 54 fields per row, plus Snap's 38 columns exactly as written if you ask for them.
- **A direct media file link** per creative (`mediaUrl`, `creatives[]`). Snap's own column links lead to an HTML page; ours is the file itself. In a sample of 360 ads across all nine years, 374 of 374 creative links answered.
- **ISO dates and codes**: `startDate` and `endDate` in ISO 8601 UTC, `countryCode` and `billingCountryCode` as ISO two letter codes, `ageMin` and `ageMax` as numbers.
- **A country filter that takes codes and names** (US or United States), and **whole word matching** on advertiser, organization, candidate and committee names.
- **A row that says why a run is empty**, and **each ad charged once** with a monitor name.

The 2026 file covers the US midterm election year: on 2026-10-06 it held 5,382 United States ads, 5,133 of which started in 2026, with USD 6.27 million of reported spend so far. Snap rewrote the files about every hour on the day we measured (2026-10-06).

This is an independent tool, not affiliated with, endorsed by or sponsored by Snap Inc. "Snapchat" and "Snap" name the data source only.

### Quick start

1. Pick the **years** (the prefill is 2026, an empty field reads the newest file, `all` reads the whole archive since 2018).
2. Optional: **countries** as codes or English names (`US`, `GB`, `United States`), and **search** terms such as an advertiser, organization or candidate name, one per line.
3. Optional filters: **startedFrom** and **startedTo** (or **startedWithinDays**), **status** (`active` or `ended`), **minSpend**, **minImpressions**, **currencies**, **targetRegions** (for example `Pennsylvania`).
4. Choose **sortBy** (`newest`, `spend` or `impressions`) and set **maxItems** (the prefill is 20; 100 when the field is left out). Run, then export the dataset as JSON, CSV or Excel, or read it through the API.
5. To receive only new ads on a schedule, give a **monitorName** such as `us-midterms-2026` and schedule the run.

### What you get

#### Political ad row

One row per ad (`type` = `politicalAd`). Fill rates are measured over all 80,162 ads in the archive on 2026-10-06; a derived field is filled when the column it comes from is.

| Field | What it is | Filled |
|---|---|---|
| `adId` | Snap's ad id (64 hex characters) | 100% |
| `archiveYear` | The yearly file the ad sits in | 100% |
| `payingAdvertiserName` | Who paid for the ad | 100% |
| `organizationName` | The organization that ran the ad (often the agency) | 100% |
| `billingAddress`, `billingCountryCode` | Billing address as Snap writes it, and its ISO country code | 100% (address) |
| `candidateBallotInformation` | Candidate or ballot measure | 37.6% |
| `committeeName`, `committeeIdentificationNumber`, `disclosureNameOfCommittee` | Committee details | 2.4% each |
| `advertisingJurisdiction` | Jurisdiction stated for the ad | 2.4% |
| `spend`, `currency` | Spend to the day the file was written, in the ad's own currency | 100% |
| `impressions` | Impressions to the day the file was written | 100% |
| `cpm` | Spend per 1,000 impressions, computed (null when impressions is 0) | from spend and impressions |
| `startDate`, `endDate` | ISO 8601 UTC | 100%, 83.2% |
| `isActive` | Started and not ended at the moment the run started | from the dates |
| `countryCode`, `country` | ISO code and English name of the delivery country | 98.1% |
| `mediaUrl`, `mediaType`, `creativeCount`, `creatives[]` | Direct media file link of the first creative, its type, and every creative with `pageUrl`, `mediaUrl`, `mediaType` | 99.8% |
| `landingUrl`, `callToActionLinks`, `creativeProperties` | Landing link and the call to action links | 86.3% (creativeProperties) |
| `ageBracket`, `ageMin`, `ageMax` | Targeted ages as written and as numbers | 96.3% |
| `gender` | Targeted gender | 10.6% |
| `regionsIncluded`, `regionsExcluded` | Targeted states and regions | 37.8%, 7.0% |
| `electoralDistrictsIncluded`, `electoralDistrictsExcluded` | Targeted electoral districts | 0.9%, under 0.1% |
| `metrosIncluded`, `metrosExcluded` | Targeted metro areas | 8.9%, 1.3% |
| `postalCodesIncluded`, `postalCodesExcluded` | Targeted postal codes | 14.8%, 1.9% |
| `radiusTargetingIncluded`, `radiusTargetingExcluded` | Circles as `latitude`, `longitude`, `radius` | 5.3%, 0.2% |
| `locationCategoriesIncluded`, `locationCategoriesExcluded` | Location categories | under 0.1% |
| `interests` | Targeted interests | 21.1% |
| `segments` | Audience segments | 53.3% |
| `languages` | Targeted languages | 31.0% |
| `advancedDemographics` | Advanced demographics | 3.1% |
| `osType`, `targetingConnectionType`, `targetingCarriers` | Device and network targeting | 5.0%, 0.2%, under 0.1% |
| `matchedSearch` | Which of your search terms and fields matched (only with search) | when searched |
| `sourceFileUrl`, `sourceFileUpdatedAt` | The yearly file and the time Snap last wrote it | 100% |
| `sourceColumns` | Snap's 38 columns exactly as written (only with includeSourceColumns) | optional |
| `scrapedAt` | When the row was made | 100% |

One real row from a run on 2026-10-06 (full row, no field removed):

```json
{
  "type": "politicalAd",
  "adId": "15d04ab14a81f30d7a4bfe73587b15979be27047b2611d6c20b1ca33ecc990dc",
  "archiveYear": 2026,
  "payingAdvertiserName": "No on Prop 40",
  "organizationName": "GMMB, Inc",
  "candidateBallotInformation": "40",
  "currency": "USD",
  "spend": 257,
  "impressions": 30889,
  "cpm": 8.3201,
  "startDate": "2026-10-06T04:00:13Z",
  "endDate": "2026-10-13T03:59:00Z",
  "isActive": true,
  "countryCode": "US",
  "country": "United States",
  "mediaUrl": "https://storage.googleapis.com/ad-manager-political-ads-dump-shadow/2839e2452cba744e7d3f35d730346588260b97b1b74c24598f4ba04aaf90a987.mp4",
  "mediaType": "mp4",
  "creativeCount": 1,
  "creatives": [
    {
      "pageUrl": "https://www.snap.com/political-ads/asset/2839e2452cba744e7d3f35d730346588260b97b1b74c24598f4ba04aaf90a987?mediaType=mp4",
      "mediaUrl": "https://storage.googleapis.com/ad-manager-political-ads-dump-shadow/2839e2452cba744e7d3f35d730346588260b97b1b74c24598f4ba04aaf90a987.mp4",
      "mediaType": "mp4"
    }
  ],
  "landingUrl": "https://www.factson40.org/?&utm_medium=paid-social&utm_content=List&utm_campaign=NoOn40",
  "callToActionLinks": [
    {
      "type": "web_view_url",
      "url": "https://www.factson40.org/?&utm_medium=paid-social&utm_content=List&utm_campaign=NoOn40"
    }
  ],
  "billingAddress": "3050 K Street,Washington,20007,US",
  "billingCountryCode": "US",
  "committeeName": "No on Prop 40 - Doctors, Teachers, Small Businesses, Working Families and Public Safety Against the Reckless Wealth Tax Experiment",
  "committeeIdentificationNumber": "1492108",
  "disclosureNameOfCommittee": "No on Prop 40 - Doctors, Teachers, Small Businesses, Working Families and Public Safety Against the Reckless Wealth Tax Experiment. Ad committee’s top funders: California Primary Care Association Advocates & California Medical Association.",
  "advertisingJurisdiction": "California",
  "gender": null,
  "ageBracket": "18+",
  "ageMin": 18,
  "ageMax": null,
  "regionsIncluded": [
    "California"
  ],
  "regionsExcluded": [],
  "electoralDistrictsIncluded": [],
  "electoralDistrictsExcluded": [],
  "radiusTargetingIncluded": [],
  "radiusTargetingExcluded": [],
  "metrosIncluded": [],
  "metrosExcluded": [],
  "postalCodesIncluded": [],
  "postalCodesExcluded": [],
  "locationCategoriesIncluded": [],
  "locationCategoriesExcluded": [],
  "interests": [],
  "osType": null,
  "segments": null,
  "languages": [],
  "advancedDemographics": [],
  "targetingConnectionType": null,
  "targetingCarriers": [],
  "creativeProperties": "web_view_url:https://www.factson40.org/?&utm_medium=paid-social&utm_content=List&utm_campaign=NoOn40",
  "sourceFileUrl": "https://storage.googleapis.com/ad-manager-political-ads-dump/political/2026/PoliticalAds.zip",
  "sourceFileUpdatedAt": "2026-10-06T11:11:36.000Z",
  "scrapedAt": "2026-10-06T11:55:12.389Z"
}
```

#### Status and summary rows (free)

Every run ends with rows that say what happened. They are never charged.

| `type` / `status` | When |
|---|---|
| `status` / `invalid_input` | One row listing every problem in the input; the run reads no file |
| `status` / `not_published` | A year you asked for has no file |
| `status` / `failed` | A yearly file could not be read; the other years go on |
| `status` / `partly_read` | Some records of a yearly file were damaged and left out; the rest was delivered and the summary says the coverage is not complete |
| `status` / `no_ads` | Nothing matched, or everything was delivered before under the monitor name |
| `status` / `limit_reached` | The row cap (maxItems) or the run's charge limit was reached, with the number of ads that matched and were not delivered |
| `status` / `monitor_unavailable` | The monitor name is in use by another run, or its memory could not be opened or saved; ads delivered after a failed save are not charged |
| `status` / `stopped` | The run was stopped before it finished, with the number of ads delivered |
| `summary` | One per run: counts per year and per search term, and the billing counters |

### How much does it cost to scrape Snapchat political ads?

You pay per Political ad row delivered plus a small start fee per run. Status rows and the run summary are free, and so are ads that do not pass your filters.

| Event | FREE | BRONZE | SILVER | GOLD |
|---|---|---|---|---|
| Political ad (`political-ad`, one ad delivered as a row) | $0.50 / 1,000 | $0.50 / 1,000 | $0.45 / 1,000 | $0.40 / 1,000 |
| Actor start (`apify-actor-start`, once per run) | $0.004 | $0.004 | $0.004 | $0.004 |

Platinum and Diamond plans pay the Gold price. The Actor start event is a flat fee with no tier discount, charged once per run whatever the run delivers (it is charged per GB of memory, and this Actor runs at 512 MB).

The Store pricing card shows these same prices per 1,000 events: "$0.50 / 1,000" on the Political ad row means one ad costs 0.05 cents.

Worked examples (start fee included, ad counts of 2026-10-06):

| Run | FREE and BRONZE | SILVER | GOLD |
|---|---|---|---|
| A search that finds nothing (the start fee) | $0.004 | $0.004 | $0.004 |
| 20 ads (the prefill) | $0.014 | $0.013 | $0.012 |
| 1,000 ads | $0.504 | $0.454 | $0.404 |
| The whole 2026 file, 8,008 ads | $4.008 | $3.6076 | $3.2072 |
| The whole archive, 80,162 ads | $40.085 | $36.0769 | $32.0688 |

Each total is the start fee plus the number of ads times the tier's price per ad: 20 ads on Free cost $0.004 + 20 x $0.0005 = $0.014. At Gold the whole archive costs $0.004 + 80,162 x $0.0004 = $32.0688, that is USD 32.07.

Speed on the platform at the default 512 MB (measured 2026-10-06): 20 ads in 3 seconds, the whole 2026 file (8,009 ads) in 9 seconds, all nine files read and searched in 5 to 6 seconds, the whole archive (80,162 ads) in about four and a half minutes.

### Input

| Input | What it does |
|---|---|
| `years` | The yearly files to read, `2018` to `2026`, or `all`. Empty: the newest file |
| `countries` | ISO two letter codes or English country names. Empty: every country |
| `search` | Names or keywords, one per line (up to 200). Matched on paying advertiser, organization, candidate or ballot information, committee name and disclosure name of the committee; capitals, accents and punctuation make no difference |
| `searchMatch` | `words` (default): every word of the term as a whole word, any order. `exact`: the field is exactly the term |
| `startedWithinDays` | Ads that started within this many days before the run started, up to the moment it started (1 to 3650). Not combined with the two date fields |
| `startedFrom`, `startedTo` | Start date window, YYYY-MM-DD |
| `status` | `all` (default), `active` or `ended`, judged at the moment the run starts |
| `minSpend` | Minimum spend in the ad's own currency, whole units |
| `minImpressions` | Minimum impressions |
| `currencies` | Three letter codes: USD, EUR, GBP, NOK, CAD, AUD, SEK, INR, DKK, NZD, AED |
| `targetRegions` | Included regions, metros or electoral districts exactly as Snap writes them, for example `Pennsylvania` or `California 45th District` |
| `sortBy` | `newest` (default), `spend` or `impressions`; decides which ads are delivered when more match than maxItems |
| `maxItems` | The most Political ad rows this run may deliver and charge (1 to 1,000,000; 100 when left out) |
| `monitorName` | Deliver only new ads: each ad is delivered and charged once per monitor name |
| `includeSourceColumns` | Add `sourceColumns` with Snap's 38 columns as written, no extra charge |

#### Monitor: deliver only new ads

Give a name such as `us-midterms-2026` and schedule the run. Each ad is delivered and charged once per monitor name; later runs skip what the monitor already delivered, including ads Snap adds to the file late. Use a new name when you change the filters. Two runs on one name at the same time: the second delivers nothing. The first run of a monitor over a large selection takes longer than a plain run (the list of delivered ads is saved after every batch); later runs deliver only what is new.

### Use cases

- **Journalists**: who paid for political ads on Snapchat in a state or district, how much they spent and which ages and interests they targeted, with the creative itself one link away.
- **Campaign analysts**: spend, impressions and CPM per advertiser, committee or ballot measure, sorted by spend, for the 2026 election year or any year since 2018.
- **Researchers**: the whole archive, 80,162 ads in 54 countries, with ISO codes and dates and Snap's own columns as written for reproducible work.
- **Ad transparency and compliance teams**: a scheduled monitor (for example `us-midterms-2026`) that delivers the ads newly added to the library, each once.

### API examples

Replace `<YOUR_APIFY_TOKEN>` with your Apify API token.

#### curl

```bash
curl -X POST "https://api.apify.com/v2/acts/automation_craft~snapchat-political-ads-scraper/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"years": ["2026"], "countries": ["US"], "targetRegions": ["Pennsylvania"], "sortBy": "spend", "maxItems": 20}'
```

#### Node.js (apify-client)

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

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('automation_craft/snapchat-political-ads-scraper').call({
    years: ['2026'],
    countries: ['United States'],
    search: ['Planned Parenthood'],
    maxItems: 20,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const item of items) {
    if (item.type === 'politicalAd') console.log(item.payingAdvertiserName, item.spend, item.currency, item.mediaUrl);
}
```

#### Python (apify-client)

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("automation_craft/snapchat-political-ads-scraper").call(run_input={
    "years": ["2026"],
    "countries": ["US"],
    "status": "active",
    "monitorName": "us-midterms-2026",
    "maxItems": 1000,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    if item["type"] == "politicalAd":
        print(item["payingAdvertiserName"], item["regionsIncluded"], item["spend"])
```

### What this Actor does not do

- It does not return commercial ads from Snapchat's EU Ads Gallery. This Actor reads the Political Ads Library only.
- It does not search sponsored creator content, which is part of the Ads Gallery, not of the Political Ads Library.
- It has no count only mode: the free summary row of every run carries the number of ads that matched, per year and per search term, so a run with `maxItems` 1 gives you the counts.
- It has no option to leave out or mask the billing address: the row carries the 38 columns of Snap's public file, and Snap's file describes this one as the address of the organization that created the ad. Drop the field on your side if you do not want it.
- It does not convert spend to one currency: the archive has 11 currencies and amounts are as Snap reports them.
- It keeps no change history: each run returns Snap's current totals, and the spend and impressions of running ads change from day to day (1,627 of 7,961 ads of the 2026 file changed between 2026-10-05 and 2026-10-06). A monitor delivers an ad once and not its later updates.
- It does not check the bytes of media files: `mediaType` is the type Snap's link names (in a sample, 19 of 65 files named png held JPEG data).
- It links media files and does not download them.
- It does not state the unit of radius targeting, because Snap does not.
- It does not move ads between years: an ad sits in the yearly file Snap assigned it to, which is not the start year for about 1 percent of ads.
- It does not show ads before Snap publishes them: ads appear in the file when Snap publishes them, sometimes days or months after their start date.
- It does not predict anything, and it does not cover TV, other platforms or ads Snap has not published.
- It grants no licence: Snap states no licence for the files, so check your own use.

### FAQ

#### How much is spent on Snapchat political ads?

On 2026-10-06 the archive held 80,162 ads since 2018 in 54 countries, 58,484 (73 percent) of them in the United States. The 2026 file held 5,382 United States ads, 5,133 of which started in 2026, with USD 6.27 million of reported spend. Sort by `spend` to see the biggest ads; amounts stay in each ad's own currency.

#### How were Snapchat political ads targeted?

Each row carries the targeting Snap publishes: ages (`ageMin`, `ageMax`), `gender`, `regionsIncluded`, `electoralDistrictsIncluded`, `metrosIncluded`, `postalCodesIncluded`, radius circles, `interests`, `segments` and `languages`. Filter on a state, metro or district with `targetRegions`; fill rates per field are in the table above.

#### Who paid for a Snapchat political ad?

Every row names the paying advertiser (`payingAdvertiserName`), the organization that ran it (`organizationName`) and the billing address, and where Snap gives them the candidate or ballot measure and the committee name and id. Search advertiser, organization, candidate and committee names with `search`, whole word by default.

#### Can I track Snapchat political ads for the 2026 midterms?

Yes, for ads Snap publishes: the 2026 file covers the election year, and a scheduled run with a `monitorName` such as `us-midterms-2026` delivers the newly added ads, each once, including ads Snap adds late. It does not predict results or cover TV or other platforms.

#### Does this Actor return commercial Snapchat ads?

No. It does not return commercial ads from Snapchat's EU Ads Gallery. This Actor reads the Political Ads Library only.

#### Why does this Actor run with limited permissions?

It runs with Apify's limited permissions, the least privilege level: it reads its input and writes only its own run's storages. The one exception is the monitor: when you give a `monitorName`, it opens a named key-value store it creates itself (`snap-political-monitor-v1-...`) to remember which ads it delivered. It touches nothing else in your account.

### Changelog

See [CHANGELOG.md](CHANGELOG.md). 0.1 (2026-10-06): first release.

### More data tools by Automation Craft

Ad libraries: [Meta Ad Library Scraper - All Placements, Filters](https://apify.com/automation_craft/meta-ads-library-scraper), [Facebook Ads Library Scraper - Page Ads, No Login](https://apify.com/automation_craft/facebook-ads-library-scraper), [Instagram Ads Library Scraper - Creatives, Video](https://apify.com/automation_craft/instagram-ads-library-scraper), [TikTok Ads Library Scraper: EU Ads, No Login](https://apify.com/automation_craft/tiktok-ads-library-scraper), [TikTok Creative Center Scraper: Top Ads, No Login](https://apify.com/automation_craft/tiktok-creative-center-scraper), [Google Ads Transparency Scraper - Decoded Creatives](https://apify.com/automation_craft/google-ads-transparency-scraper), [Google Ads Library Scraper - Competitor Ads, No Login](https://apify.com/automation_craft/google-ads-library-scraper), [YouTube Ads Scraper - Video Ads by Advertiser](https://apify.com/automation_craft/youtube-ads-scraper), [LinkedIn Ad Library Scraper: Ads by Company](https://apify.com/automation_craft/linkedin-ad-library-scraper).

Other data: [Google News Scraper: Search, Topics, Decoded URLs](https://apify.com/automation_craft/google-news-scraper), [Substack Scraper: Posts, Notes and Profiles](https://apify.com/automation_craft/substack-scraper), [Google Trends Scraper - Compare and Trending Now](https://apify.com/automation_craft/google-trends-scraper), [Telegram Channel Scraper: Posts, Views, Dates](https://apify.com/automation_craft/telegram-channel-scraper), [SEC Form D Scraper: Offerings & Funding Leads](https://apify.com/automation_craft/sec-form-d-scraper).

# Changelog

This Actor's version history is a separate document: https://apify.com/automation_craft/snapchat-political-ads-scraper/changelog.md

# Actor input Schema

## `years` (type: `array`):

The yearly files to read. Pick one or several, or All years for the whole archive since 2018. An ad sits in the file of the year Snap assigned it to, which is the year it started in for 99 percent of ads. Leave empty for the newest yearly file. Through the API pass years as text, for example \["2026", "2024"], or \["all"].

## `countries` (type: `array`):

Keep only ads delivered in these countries. Use ISO two letter codes such as US, GB, FR, NO, or English country names such as United States. Leave empty for every country. The archive holds ads from 54 countries; about 73 percent are United States ads.

## `search` (type: `array`):

Names or keywords, one per line, for example Planned Parenthood, or Proposition 50. An ad matches when every word of a term appears as a whole word in ONE of these fields: paying advertiser, organization, candidate or ballot information, committee name, disclosure name of the committee. Capitals, accents and punctuation make no difference. Several terms: an ad that matches any of them is delivered once, and the row says which terms and fields matched. A term nobody matches costs nothing; the run summary counts the matches per term. Up to 200 terms.

## `searchMatch` (type: `string`):

words: every word of the term appears in the field as a whole word, in any order (Biden finds Biden for President). exact: the field is exactly the term, word for word.

## `startedWithinDays` (type: `integer`):

Keep only ads whose start date is within this many days before the run started, up to the moment it started, for example 7. Cannot be combined with the two date fields below. Note that Snap adds some ads to the file days or months after their start date; to catch every new ad on a schedule use a monitor name instead.

## `startedFrom` (type: `string`):

Keep only ads whose start date is on or after this day, YYYY-MM-DD, for example 2026-01-01.

## `startedTo` (type: `string`):

Keep only ads whose start date is on or before this day, YYYY-MM-DD.

## `status` (type: `string`):

all: every ad. active: ads that have started and have no end date in the past, judged at the moment the run starts. ended: ads whose end date has passed.

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

Keep only ads that spent at least this amount, in the ad's own currency, whole units, for example 1000. Snap reports spend per ad as the total up to the day the file was written.

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

Keep only ads with at least this many impressions, for example 100000.

## `currencies` (type: `array`):

Keep only ads billed in these currencies, as three letter codes: USD, EUR, GBP, NOK, CAD, AUD, SEK, INR, DKK, NZD, AED. Leave empty for every currency.

## `targetRegions` (type: `array`):

Keep only ads whose included regions, metros or electoral districts name one of these, exactly as Snap writes them, one per line: for example Pennsylvania, Arizona, Las Vegas, California 45th District. Capitals make no difference. An ad that targets a whole country without naming regions does not match.

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

The order of the rows, which also decides which ads are delivered when more match than the row cap allows. newest: latest start date first. spend: highest spend first (amounts in different currencies are compared as plain numbers). impressions: most impressions first.

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

The most Political ad rows this run may deliver (and charge). A free row says how many more matched. When the field is left out, 100 is used. For a whole yearly file set it above the file's size, for example 100000.

## `monitorName` (type: `string`):

Give a name, for example us-midterms-2026, and schedule the run: each ad is delivered and charged once per monitor name, later runs skip what the monitor already delivered, including ads Snap adds to the file late. Use a new name when you change the filters. Two runs on one name at the same time: the second delivers nothing. Leave empty for a plain run.

## `includeSourceColumns` (type: `boolean`):

Adds an object sourceColumns to every row with the 38 columns of Snap's file exactly as the file has them (column names and text unchanged), next to the parsed fields. For researchers who want to reproduce the original CSV. No extra charge.

## Actor input object example

```json
{
  "years": [
    "2026"
  ],
  "countries": [
    "US"
  ],
  "searchMatch": "words",
  "status": "all",
  "sortBy": "newest",
  "maxItems": 20,
  "includeSourceColumns": false
}
```

# Actor output Schema

## `items` (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 = {
    "years": [
        "2026"
    ],
    "countries": [
        "US"
    ],
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation_craft/snapchat-political-ads-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 = {
    "years": ["2026"],
    "countries": ["US"],
    "maxItems": 20,
}

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

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

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

```

## CLI example

```bash
echo '{
  "years": [
    "2026"
  ],
  "countries": [
    "US"
  ],
  "maxItems": 20
}' |
apify call automation_craft/snapchat-political-ads-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation_craft/snapchat-political-ads-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/T7BJsYlfDSgzVgFmW/builds/RVAK4zqco85ShYU9K/openapi.json
