RedditapisRedditapis
Listings & Search

Reddit Political Ads Data as JSON (Spend, Targeting)

Every political ad Reddit has disclosed since 2019, parsed into advertiser, spend band, impressions, run dates and subreddit targeting.

GET/api/reddit/political-ads$0.0015 / call

Reddit's political-ad disclosures, parsed into fields.

Reddit publishes one post per political ad it runs in r/RedditPoliticalAds: who paid, how much, how many impressions, where it ran and which subreddits it targeted. The posts are written as bulleted text whose labels changed over the years. This endpoint reads the feed and returns each disclosure as structured data, so you can sort advertisers by spend or find every ad that targeted a subreddit without parsing prose.

Query Parameters

ParameterTypeRequiredDescription
sortstringNonew (default, most recent disclosure first), top or hot
tstringNoTime window for sort=top: hour | day | week | month | year | all
limitnumberNoPosts to read, 1-100 (default 25)
afterstringNoPagination cursor, see Pagination depth

limit counts posts read, and posts that are not disclosures (announcements, policy posts) are left out, so a page can hold fewer ads than limit. skipped says how many were left out.

Paging past Reddit's cap

Reddit closes a single listing near 1000 items and then stops issuing a cursor, so listing_status: truncated is Reddit's limit rather than the end of the data. Every distinct combination of parameters you send is a separate listing with its own budget, so widen across listings rather than paging deeper into one.

What you can vary here:

  • sort takes new, top, hot, each with its own cursor.
  • t takes hour, day, week, month, year, all. We forward it only on sort=top and sort=controversial and drop it on the other sorts, so sort=new&t=week and sort=new&t=all are the same request.

How far these actually widen has not been measured on this endpoint. On /api/reddit/posts two sorts ranged from 0 to 99 shared items out of 100 depending on how busy the subreddit was, so read a page of each before assuming a second sort doubles your coverage.

Example

curl -H "Authorization: Bearer $TOKEN" \
  "https://api.redditapis.com/api/reddit/political-ads?limit=100"
const response = await fetch(
  "https://api.redditapis.com/api/reddit/political-ads?limit=100",
  { headers: { Authorization: "Bearer TOKEN" } }
);
const { ads, after } = await response.json();
import requests

response = requests.get(
    "https://api.redditapis.com/api/reddit/political-ads",
    params={"limit": 100},
    headers={"Authorization": "Bearer TOKEN"},
)
data = response.json()

Response Shape

{
  "ads": [
    {
      "advertiser": "Better Markets",
      "ein": "27-2227363",
      "fec_id": null,
      "committee_type": null,
      "tax_exempt_status": "501(c)(3)",
      "treasurer": null,
      "billing_name": null,
      "billing_zip": null,
      "mailing_address": "2000 Pennsylvania Ave NW, Suite 4008, Washington, DC 20006",
      "spend_usd": { "raw": "≤ $280,174.85", "min": null, "max": 280174.85 },
      "impressions": { "raw": "29,480,112", "min": 29480112, "max": 29480112 },
      "start_date": "2026-06-10",
      "end_date": "2026-07-26",
      "geo_targeting": ["United States"],
      "negative_geo_targeting": [],
      "interest_targeting": ["Business & Finance"],
      "negative_interest_targeting": [],
      "targeted_subreddits": ["Bogleheads", "Daytrading", "investing"],
      "negatively_targeted_subreddits": [],
      "ad_links": ["https://www.reddit.com/user/BetterMarkets/comments/1ucwa4k/..."],
      "category": "Issue Ads",
      "post": { "...": "the disclosure post, same shape as /api/reddit/posts" }
    }
  ],
  "skipped": 1,
  "after": "..."
}

Fields

FieldMeaning
advertiserThe organization, committee or campaign that bought the ad
ein, fec_idThe tax id (issue ads) or Federal Election Commission committee id (campaign ads), whichever the disclosure carries
spend_usd, impressionsraw is the text Reddit published. Most are bands ($1k - $50k), recent ones an upper bound (≤ $280,174.85) or an exact count. min and max are the numbers; a bound the post does not state is null.
start_date, end_dateWhen the ad ran, as YYYY-MM-DD
targeted_subredditsSubreddit names without r/, in the order published, duplicates removed
categoryThe post's flair, such as Issue Ads, Presidential Candidate Ad 2020 or Approved in Error (an ad Reddit later found broke its policy)

A field a disclosure does not carry is null (or an empty list); nothing is filled in from a default. Older disclosures use different labels for the same thing (Advertiser/Organization, Committee name, Name of Organization), and all of them land in the same field.

Errors

StatusWhen
400sort or t is not one of the listed values, or limit is out of range

Billed at the standard read price, $0.0015 per call.

Independent third-party API for developers and researchers. Not affiliated with, endorsed by, or sponsored by Reddit, Inc.

On this page