# Revcontent Ads Scraper - Native Ads, Advertisers (`automation_craft/revcontent-ads-scraper`) Actor

Scrape the native ads Revcontent runs right now in the sponsored boxes of verified publisher sites, read from 23 countries, or any page URL. One row per distinct ad: headline, image, brand, advertiser id, campaign id and landing address where served. Keyword and brand filters; watch mode.

- **URL**: https://apify.com/automation_craft/revcontent-ads-scraper.md
- **Developed by:** [Automation Craft](https://apify.com/automation_craft) (community)
- **Categories:** Marketing, Lead generation, SEO tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.85 / 1,000 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

### Revcontent Ads Scraper - Native Ads, Advertisers

**Revcontent ads scraper** for the native ads running right now in Revcontent's sponsored content boxes ("Around the Web", "Sponsored stories") on news and publisher sites. Pick countries, pick sites, or paste any article URL, and get one row per distinct ad: headline, description, image, brand, Revcontent's **advertiser id and campaign id**, the landing address where the box states one, and the eCPM figure older boxes carry. No login, no API key, no browser. Each distinct ad is charged once per run, and a watch mode charges only ads your earlier runs have not seen.

This is a live sampler of the sponsored content Revcontent serves today, per country and per site, built for affiliate marketers, media buyers and agencies who study competitor native ads. It is not an ad library: Revcontent publishes no archive, so there are no first and last shown dates and no history before your own runs (see "What this Actor does NOT do").

#### Quick start

1. Open the Actor and keep the prefilled input (United States, 3 verified sites, 20 ads), or pick your countries.
2. Optionally pick named sites from the built in list, or paste article URLs of any site that shows a Revcontent box.
3. Optionally narrow the ads with keywords, brands, advertiser ids, landing domains or media types: ads that do not match are not delivered and not charged.
4. Click Start. A run of the prefilled input takes a few seconds.
5. Read the **Ads** view: its first column, `type`, tells the rows apart (`ad` for an ad, charged; the run's coverage and summary rows follow with empty cells, since a dataset view cannot filter by row type). The **Coverage** view has one row per site and country: calls, answers with and without ads, distinct ads.
6. To track new native ads every day, give the run a **memory name** and schedule it: each later run delivers and charges only ads the memory has not seen.

### What you get

Each ad row carries the fields below. Fill rates are measured on 2,402 distinct ads delivered by this Actor's own runs of 2026-10-18 (build 0.1.3, 38 runs with ads; United States, United Kingdom, Canada, Australia, Germany and India exits; 2,390 of the ads from older boxes, 12 from newer boxes).

| Field | What it is | Filled |
|---|---|---|
| `headline` | Headline: the ad's headline as the box shows it (where Revcontent writes the reader's city or state into an ad's text, the row says {city} or {state} in its place) | 100 percent |
| `description` | Description: the ad's second line | 99.5 percent |
| `brandName` | Brand: the brand name shown with the ad | 100 percent |
| `adId` | Ad id: Revcontent's content id, the same on every site and call | 100 percent |
| `advertiserId` | Advertiser id: Revcontent's advertiser id (older boxes carry it in the item, newer boxes in their impression record) | 100 percent |
| `campaignId` | Campaign id: Revcontent's campaign id | 100 percent |
| `imageUrl`, `imageSourceUrl` | Image: the image as Revcontent serves it, and the source address it wraps | 100 percent |
| `mediaType`, `gifUrl`, `videoUrl` | Media type: `image`, `animated` (the ad carries a gif) or `video`, with the gif or video address | 100 percent (animated 2.5 percent, video 0.2) |
| `videoDurationSeconds`, `videoHasSound`, `videoWidth`, `videoHeight`, `videoBytes` | On every ad with a video, free: its length in seconds, whether the file has a sound track, its picture size and file size, read from the first 64 KB of the file (`videoFactsStatus` says `read` or why not) | 4 of 4 ads with a video in these runs |
| `sceneCuts`, `shots` | With Video scene cuts on (a paid add-on, the Scene list event): the seconds where the video cuts to a new shot, and each shot's start, end and motion (0 to 1), from ffmpeg's scene scores inside the run (`videoScenesStatus` says `read` or why not) | 1 of 1 ad with a video in the run with Video scene cuts on |
| `landingUrl`, `landingDomain`, `landingUtm` | Landing address as a newer box states it (often the advertiser's own tracking address, with Revcontent's macros unfilled), its domain and its utm parameters; older boxes carry only Revcontent's click counter, which is never followed or delivered | `landingUrl` and `landingDomain`: 100 percent of ads from newer boxes (12 of 12), none from older boxes, so it depends on the sites read (0.5 percent of these runs); `landingUtm`: 1 of the 12 |
| `ecpm` | The eCPM figure an older box states for the ad, as Revcontent sends it (Revcontent does not document its meaning) | 98.4 percent of ads from older boxes |
| `contentTags` | Revcontent's content tag numbers on older boxes (Revcontent publishes no name table) | 100 percent of ads from older boxes |
| `optimizeFor` | What the campaign is optimised for, as Revcontent states it (`cpc` on most ads) | 100 percent |
| `isProgrammatic` | True for ads from Revcontent's programmatic demand (they share one content id, so the image tells them apart) | true on 0.5 percent |
| `offerPrices`, `offerPercents`, `offerTypes`, `mentionsFree` | Prices and percentages the ad's own text mentions, as written, and the kind of offer they make (`discount_percent`, `price`, `free_shipping`, `free_trial`, `free`) | a price on 0.2 percent, a percentage on 0.6, an offer kind on 1.1 |
| `angleSignals` | Selling angles the ad's words name (`urgency`, `scarcity`, `curiosity`, `authority`, `social_proof`, `savings`, `warning`), each with the word that matched: word matches from fixed lists, nothing more | at least one angle word on 89.8 percent |

Also on every ad row: `site`, `siteCountry`, `publisherId` and `publisherDomain` (as Revcontent records the box), `widgetId`, `widgetGeneration` (`older` or `newer` box), `pageUrl`, `exitCountry` (the country the call was made from: Revcontent serves the ads of that country), `egress` (`container`, `datacenter`, `residential` or `custom`), `position` in the box, `matchedFilters` (what your filters matched), `runTag`, `seenAt`, `personalDataMasked`, `creativeId`, `adKey`, and with Save image files on, `imageFileKey`, `imageFileUrl` and `imageFileStatus` (`saved`, or why there is no file: `not_read`, `not_saved`, `no_image_address`, `not_read_work_allowance`; a row without a file carries no Image file event); with Include the raw item on, `rawItem` (Revcontent's own descriptive fields of the item; never the click link, the event trackers or the request tokens).

The run also writes free rows:

- **coverage**, one per site and country read: calls by egress, answers with ads, answers without ads (only the publisher's own links or an empty box: retried, then the site closes as `blocked`; never read as "this site shows no ads"), answers served for another country (not delivered), box generation switches, failed calls, publisher links skipped, distinct ads, ads delivered, ads your filters left out, ads over the per advertiser cap, ads already seen on another site in the run, ads your memory already knew, known ads listed, their keys, where the widget id came from, and why the site stopped (`dry`, `site_call_cap`, `blocked`, `failed`, `unknown_widget`, `no_revcontent_box`, `stopped`).
- **known_ad**, with a memory name and Also list ads the memory knows on: each ad your memory already holds, once per run, with `firstDeliveredOn` and `daysSinceFirstDelivered` (how long it has kept running across your runs). Never charged.
- **advertiser**, with Advertiser rows on: one row per advertiser id of the delivered ads, with its brands, campaigns, landing domains, sites, exit countries, media types, ad count and first and last time seen in the run. Never charged.
- **status**, for a value that could not be used (a page URL that is not a URL or is not accepted, dataset rows without a URL), a country with no verified site, or the pairs a stopped run did not reach.
- **summary**, the last row: calls by egress, page reads, ads seen, delivered, filtered out and charged, image files, batches, the stop reason, proxy bytes and the work allowance.

#### Built in sites

4,724 publisher sites are built in (United States 4,594, Canada 21, United Kingdom 71, Australia 1, Germany 5, France 2, Spain 3, Italy 21, Sweden 1, Brazil 2, South Africa 3). They come from two lists: the domains of Revcontent's own list of its publishers (its sellers.json file, each home page read once for its Revcontent box) and a walk of Revcontent's widget ids (each live widget names its publisher's domain); each site was then verified live: three calls from Apify's US addresses, at least two of them answering with sponsored rows, every answer naming the same site. A site whose domain ending names another country is listed under that country only when it also answered sponsored rows on 2 of 3 calls from a residential exit there; every other site is listed under the United States. A site found by the widget walk is one whose box Revcontent still serves; whether every such site shows the box on its pages today was not checked page by page. Pick them by country (the sites with the most ads per call first) or by name. The list is refreshed by a script (the site map), so sites that drop Revcontent leave it.

12 more countries are offered with no site of their own: New Zealand, Ireland, Netherlands, Poland, India, Mexico, Argentina, Colombia, Japan, Nigeria, Philippines, United Arab Emirates. Revcontent answered sponsored rows to residential exits in each of them on the built in sites (measured 2026-10-15), and they are read on the best verified sites from their own exits.

| Country | Sites | Sites, the most ads per call first (any built in site can be named in the Sites field of the input) |
|---|---|---|
| United States (`US`) | 4,594 | snackhistory.com, learnaboutnature.com, boxingdaily.com, caasimada.net, izismile.com, therightscoop.com, supernutritious.net, typographyu.com, ocregister.com, newsmax.com, celebsweek.com, americainsider.org, thehill.com, pjnewsletter.com, americanjournaldaily.com, stateofunion.org, usdailychronicle.com, theredonlooker.com, abc-7.com, celeblivewire.com, topdealsaccess.com, nbc-2.com, dailyacedeals.com, holywordcompanion.com, retiredrefresh.com, centralhoroscope.com, crimesflash.com, lowkickmma.com, lifemgzn.com, gzone.site and 4,564 more |
| Canada (`CA`) | 21 | besthealthmag.ca, readersdigest.ca, selection.ca, foxfmonline.ca, play1013.ca, x929.ca, 957cruzfm.ca, play92.ca, play1037.ca, kelownadailycourier.ca, blazingcatfur.ca, jetsnation.ca, vernonmatters.ca, chatnewstoday.ca, ckpgtoday.ca, flamesnation.ca, fraservalleytoday.ca, newwestrecord.ca, energeticcity.ca, news.money.ca, news.globeandmail.ca |
| United Kingdom (`GB`) | 71 | 49s.co.uk, spoil.soapsnews.uk, celeb.usainsights.uk, celeb.usatoday.uk, celebritybuzz.uk, celebrityhub.uk, soaprecap.uk, usaexplorers.uk, celeb.celebrityhub.uk, celebcell.uk, usainsights.uk, dailystory.uk, soapsecrets.uk, mobibobi.co.uk, televisiondrama.uk, celebrityinsider.uk, soapplottwist.uk, soapshub.uk, soapsnews.uk, celebritycell.uk, conservativewoman.co.uk, dailysoap.uk, soapsdrama.uk, spoilersleuths.uk, usastory.uk, usatoday.uk, cbstopnews.uk, celebgossip.uk, royalmailchat.co.uk, soapspoilers.uk and 41 more |
| Australia (`AU`) | 1 | prospectingaustralia.com.au |
| Germany (`DE`) | 5 | reitschuster.de, cichlidenwelt.de, focusrsforum.de, ketoforum.de, focusstforum.de |
| France (`FR`) | 2 | bebasket.fr, mariefrance.fr |
| Spain (`ES`) | 3 | actualidad.es, diariodeltriatlon.es, tvguia.es |
| Italy (`IT`) | 21 | gossip.it, isaechia.it, 01net.it, blogmamma.it, cucina-naturale.it, rintraccialamiaspedizione.it, sportmagazine.it, tuobenessere.it, viaggiamo.it, automobile360.it, donnemagazine.it, filastrocche.it, foodblog.it, ilreporter.it, latin.it, mybeauty.it, offerteshopping.it, okmugello.it, periodofertile.it, swingfever.it, agimeg.it |
| Sweden (`SE`) | 1 | samnytt.se |
| Brazil (`BR`) | 2 | webvolei.com.br, tudogostoso.com.br |
| South Africa (`ZA`) | 3 | news365.co.za, avforums.co.za, koby.co.za |

#### How a run reads the boxes

Revcontent has two generations of boxes, and each answers its own public data call; the built in list records the generation of every site, and for a page you paste the Actor reads the page once to find its box and generation. The United States is read from Apify's own US addresses, the run container and datacenter exits in turn (the datacenter exits sit in different US states, and Revcontent targets some ads by state); a site that answers twice in a row without a sponsored row moves to a residential US exit. Every other country is read from a residential exit in it. An answer served for another country than the one asked (a residential exit placed elsewhere) is not delivered. Each run reads the chosen sites in rounds, one call per site per round, at most two calls at a time and one new call every 250 ms; a site stops when its calls bring no new ad (`stopAfterDryCalls`), at its call limit, or when it answers without sponsored rows three times in a row.

Ads are delivered in batches: a batch is delivered when it holds 25 ads, after six rounds or 15 seconds, and when the run stops; one dataset write, one save and one charge per batch. A run that is aborted or reaches its timeout does not deliver the batch it was holding, and those ads are not charged.

#### Filters

Revcontent has no search, so filters are applied to the ads each answer carries, before the ad is charged: **keywords** and **exclude keywords** (whole words in the headline, description or brand; "phrase" keeps the words in order, "anyWord" takes any one of them, and an excluded keyword leaves out every ad the same keyword would match), **brands** (the brand name, without letter case, accents written apart, punctuation or spacing), **advertiser ids**, **landing domains** (newer boxes only: older boxes state no landing address, so their ads never pass this filter) and **media types**. Ads left out are counted in the coverage rows. A narrow filter on a small pool reads more calls for each ad delivered; a site stops after `stopAfterDryCalls` answers in a row without a new matching ad.

#### Watch mode

Give scheduled runs a **memory name**: an ad delivered under that name is never delivered or charged again under it. The memory belongs to this Actor; two runs with one memory name at the same time cannot both be charged for their ads (the second delivers its ads free and says so; each run pays its start fee). Turn on **Also list ads the memory knows** to get each known ad once per run as a free `known_ad` row with the day it was first delivered, which shows which ads keep running.

### How much does it cost to scrape Revcontent ads?

Pay per event: you pay for the ads delivered and for the add-ons you turn on (image files, scene lists), never for blocked or empty answers, page reads, repeats, filtered ads, video facts, coverage, advertiser or status rows.

| Event | Free plan | Bronze | Silver | Gold |
|---|---|---|---|---|
| Ad (per 1,000) | $1.45 | $1.25 | $1.05 | $0.85 |
| Image file (per 1,000, only with Save image files) | $0.70 | $0.64 | $0.58 | $0.50 |
| Scene list (per 1,000, only with Video scene cuts, only for ads with a video) | $1.40 | $1.28 | $1.16 | $1.00 |
| Actor start (once per run, 256 MB) | $0.008 | $0.008 | $0.008 | $0.008 |

Platinum and Diamond plans pay the Gold price. The Store pricing card shows these same prices per 1,000 events: "$0.85 / 1,000" on the Ad row means one ad costs $0.00085 on the Gold plan. The Actor start event is charged once per run on every plan, with no discount.

Examples on the Bronze plan: the prefilled run (20 ads) costs $0.008 + 20 x $0.00125 = $0.033. A run of 1,000 ads costs $0.008 + $1.25 = $1.258. With Save image files, 1,000 ads and their images cost $0.008 + $1.25 + $0.64 = $1.898. A watch run that finds 10 new ads costs $0.008 + $0.0125 = $0.0205.

A run ends early, and says so in its summary (`stoppedBy: work_allowance`), when it keeps working without delivering: answers without new ads, pages without a box, filters nothing passes. Each run carries a fixed amount of such unpaid work plus a little more for every ad it delivers, so the work of a run stays within what its start fee and its ads pay for. The caller's own charge limit is respected: an ad enters a batch only when the money left pays for all its events. The same allowance pays for the reads that prepare a row before delivery (an image file, a video's first bytes and its scenes): in a run whose filters leave out most answers it can be spent before a video is read, and such a row says `not_read_work_allowance` and carries no Image file or Scene list event.

### Input

| Field | What it does |
|---|---|
| `countries` | Exit countries to read (codes or names); the United States when nothing else is given |
| `sitesPerCountry` | How many verified sites per country, the most ads per call first (default 5) |
| `topUpWithOtherSites` | A country with fewer own sites than asked is read on the best other verified sites from its own exit (default true) |
| `sites` | Built in sites by domain |
| `pageUrls` | Article or page URLs of any site with a Revcontent box (at most 200, together with the dataset) |
| `datasetId` | An Apify dataset of your account whose rows hold page URLs (`pageUrl`, `url` or `link`), at most 200 rows |
| `maxAds` | The most ads delivered in a run (default 100) |
| `maxCallsPerSite`, `maxCalls`, `stopAfterDryCalls` | Calls per site (default 10), calls per run (default 200), answers in a row without a new ad before a site stops (default 3) |
| `maxAdsPerAdvertiser` | The most ads of one advertiser id in a run |
| `keywords`, `excludeKeywords`, `keywordMatch` | Keyword filters (`phrase` or `anyWord`) |
| `brands`, `advertiserIds`, `landingDomains`, `mediaTypes` | Exact filters on brand, advertiser id, landing domain and media type |
| `saveImages` | Save each delivered ad's image file (paid add-on, Image file event) |
| `videoScenes` | For every delivered ad with a video: its scene cuts and each shot's motion, read from the video file (paid add-on, Scene list event; default off) |
| `advertiserSummary` | Free advertiser rows at the end of the run |
| `includeRawData` | Revcontent's own item on each ad row |
| `runTag` | A label copied onto every ad, coverage and advertiser row |
| `memoryName`, `includeKnownAds`, `resetMemory` | Watch mode |
| `includePersonalData` | Personal data: on, the brand is delivered exactly as Revcontent serves it, e-mail addresses included; off (default), an e-mail address in it is hidden |
| `proxyConfiguration` | Leave as is, or: RESIDENTIAL for residential exits everywhere, a datacenter group for the United States, your own proxy URLs, or no proxy (United States only) |

Every setting is checked before any call. A value that cannot be used is refused, never guessed: a wrong type or an out of range number stops the run before any call (no ad is charged; the Actor start is), and an unusable site or page URL gets its own free status row while the rest goes on. A `null` or empty setting is treated as not given (the platform itself refuses `null` for a pick list setting such as `keywordMatch`: leave it out instead).

Example input:

```json
{
  "countries": ["US", "GB"],
  "sitesPerCountry": 10,
  "maxAds": 500,
  "keywords": ["seniors", "insurance"],
  "keywordMatch": "anyWord",
  "advertiserSummary": true,
  "memoryName": "revcontent watch"
}
```

### What this Actor does NOT do

- It is not an ad library: Revcontent publishes none, so there are no first and last shown dates, no days running, no date range or active status filters, and no history before your own runs (watch mode keeps your own first delivery day).
- No call to action text, impressions, spend, reach, ad language or advertiser verified flag: Revcontent's box answers carry none of them. (The video duration is read from the video file itself.)
- No video transcripts: none of the 37 distinct video files seen in this Actor's test runs (2026-10-15 to 2026-10-18, from 2 advertisers) had speech to transcribe: 33 have no sound track, and in the other 4 the speech detector found no speech. Every ad with a video gets its duration and sound track, and with Video scene cuts on its shots.
- No landing address for older boxes: their answer carries only Revcontent's click counter, and a click counter is never followed (a followed link is a paid click on someone's campaign). The Actor never clicks an ad, never visits a landing page and never sends Revcontent's impression or view events.
- No AI analysis of ads: the offer and angle fields are word matches from fixed lists.
- No adjustable speed: the pace is fixed (two calls at a time, one new call every 250 ms) to stay light on Revcontent and the publishers.
- No other ad network in this listing, and no ads from social media or search ad libraries.
- No personal data by default: Revcontent's rows name brands and advertiser ids, and an e-mail address in a brand is hidden unless `includePersonalData` is on; the caller's own address and location, which every answer echoes, are never written to a row.

### Use it from an AI agent

Through the Apify MCP server or the API, an agent can call this Actor with a small input (`countries`, `maxAds`, a `keywords` or `brands` filter) and read the `ad` rows. Rows of type `coverage`, `status` and `summary` are free diagnostics, not ads: a `blocked` or `dry` site is a fact about that box at that moment, so retry later rather than at once.

### FAQ

#### Is there an ad library for Revcontent?

No. Revcontent publishes no public ad library; its reporting tools need a publisher or advertiser login. This Actor reads the sponsored boxes themselves, the same answer a reader's browser gets, so it shows what runs now, per country and site.

#### How do I see competitors' Revcontent ads?

Pick the countries you sell in, add a brand, advertiser id or keyword filter, and run it on a schedule with a memory name: each run delivers the matching ads that are new, with their advertiser and campaign ids, so you can follow a competitor's creatives over time.

#### Which sites run Revcontent ads?

23 countries: United States, Canada, United Kingdom, Australia, New Zealand, Ireland, Germany, France, Spain, Italy, Netherlands, Sweden, Poland, India, Brazil, Mexico, Argentina, Colombia, Japan, Nigeria, Philippines, South Africa, United Arab Emirates. The United States is read from Apify's own US addresses (the run container and datacenter exits, in turn); every other country from a residential exit in it. 4,724 verified sites are built in, and any other site that shows a Revcontent box can be read with a page URL.

#### Does the Actor click ads or visit landing pages?

No. It reads the box's data call only. Revcontent's click counter, impression and view events and the landing addresses are never requested; the landing address is delivered as text where the box states one.

#### Does the Actor deliver personal data?

Rows name brands and advertiser ids. A brand can hold a person's e-mail address: by default it is replaced by "(e-mail address hidden)" and `personalDataMasked` is true on that row. The same masked form is given in `rawItem` (`provider`, `brand`) when `includeRawData` is on. Turn on `includePersonalData` to get the brand exactly as Revcontent serves it (on ad rows, in `rawItem` and in the advertiser rows' `brandNames`; the brand and keyword filters then compare that brand). You are responsible for a lawful use of personal data, GDPR included.

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

Least privilege: it runs with limited permissions and can only reach its own storages. The watch mode memory is a named store it creates itself, and image files go into the run's own key-value store.

### API examples

Run it and get the ads with curl:

```bash
curl -X POST "https://api.apify.com/v2/acts/automation_craft~revcontent-ads-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"countries": ["US"], "sitesPerCountry": 3, "maxAds": 20}'
```

Node.js:

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('automation_craft/revcontent-ads-scraper').call({ countries: ['US', 'CA'], maxAds: 200, advertiserSummary: true });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.filter((r) => r.type === 'ad').length, 'ads');
```

Python:

```python
from apify_client import ApifyClient
client = ApifyClient("YOUR_TOKEN")
run = client.actor("automation_craft/revcontent-ads-scraper").call(run_input={"countries": ["GB"], "maxAds": 100, "keywords": ["insurance"]})
ads = [r for r in client.dataset(run["defaultDatasetId"]).iterate_items() if r["type"] == "ad"]
print(len(ads), "ads")
```

### Changelog

See the Changelog tab. 0.1 (2026-10-19): new setting `includePersonalData` (off by default). 0.1 (2026-10-18): first release.

### More data tools by Automation Craft

- [Outbrain Ads Scraper - Native Ads, Advertisers](https://apify.com/automation_craft/outbrain-ads-scraper)
- [Taboola Ads Scraper - Native Ads by Country](https://apify.com/automation_craft/taboola-ads-scraper)
- [MGID Ads Scraper - Native Ads by Country, Payer](https://apify.com/automation_craft/mgid-ads-scraper)
- [Meta Ads Library Scraper - Ad Library, All Filters](https://apify.com/automation_craft/meta-ads-library-scraper)
- [Google Ads Transparency Scraper - Decoded Creatives](https://apify.com/automation_craft/google-ads-transparency-scraper)
- [TikTok Ads Library Scraper: EU Ads, No Login](https://apify.com/automation_craft/tiktok-ads-library-scraper)
- [LinkedIn Ad Library Scraper: Ads by Company](https://apify.com/automation_craft/linkedin-ad-library-scraper)
- [Microsoft Ads Library Scraper - Competitor Ads](https://apify.com/automation_craft/microsoft-ads-library-scraper)

# Changelog

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

# Actor input Schema

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

Countries to sample: Revcontent serves the ads of the reader's country, so each country is read from an exit in it (the United States from Apify's own US addresses, every other country from a residential exit there). 11 countries have verified sites of their own; the other 12 countries are read on the best verified sites from their own exits (see Top up thin countries). Leave empty with no sites and no page URLs to read the United States.

## `sitesPerCountry` (type: `integer`):

How many verified sites to read for each chosen country, the sites with the most ads per call first. 0 reads no site by country (only the sites and page URLs below). Default 5.

## `topUpWithOtherSites` (type: `boolean`):

When a chosen country has fewer verified sites of its own than Sites per country, read the best other verified sites from that country's exit to make up the number (Revcontent serves the ads of the reader's country on every site; each row names the site and its own country). Default true.

## `sites` (type: `array`):

Built in publisher sites to read by domain (4,724 sites; the suggestions are the 300 with the most ads per call), each from an exit in the site's own country as listed. A domain that is not built in gets a free status row: read its pages with Page URLs instead. Adds to the sites picked by country.

## `pageUrls` (type: `array`):

Any article or page URL of any site that shows a Revcontent box, read from every chosen country (the United States when no country is chosen). For a site that is not built in, the Actor reads the page once to find its Revcontent widget id; a page without a Revcontent box gets a free coverage row. At most 200 per run, together with the dataset below.

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

The id of an Apify dataset of your account whose rows hold page URLs (in a pageUrl, url or link field), read in full and added to Page URLs. A dataset with more than 200 rows, or one this Actor cannot read, stops the run before any further call, and no further event is charged (a fresh run pays only its Actor start).

## `maxAds` (type: `integer`):

The most ads delivered in one run (each distinct ad is one row and one charge). Default 100.

## `maxCallsPerSite` (type: `integer`):

The most times one site is read in one run (Revcontent rotates the ads it shows, so more calls find more ads). Default 10.

## `stopAfterDryCalls` (type: `integer`):

A site stops when this many answers in a row brought no ad new to the run (that passed the filters, when filters are set). Default 3.

## `maxCalls` (type: `integer`):

The most requests in one run, over all sites and countries (page reads for sites that are not built in included; image file reads not counted). Default 200.

## `maxAdsPerAdvertiser` (type: `integer`):

The most ads of one Revcontent advertiser id delivered in one run; further ads of that advertiser are counted in the coverage rows, free. Empty: no limit.

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

Deliver only ads whose headline, description or brand holds one of these keywords (as whole words, without letter case or punctuation; see Keyword match). Ads that do not match are not delivered and not charged; they are counted in the coverage rows. At most 100 keywords of up to 100 characters.

## `keywordMatch` (type: `string`):

phrase: the keyword's words in that order (default). anyWord: any one of the keyword's words. The same rule applies to Exclude keywords.

## `excludeKeywords` (type: `array`):

Leave out every ad that one of these keywords matches (by the same rule as Keywords). Left out ads are not charged.

## `brands` (type: `array`):

Deliver only ads whose brand (the name the box shows) is one of these, compared without letter case, accents written apart, punctuation or spacing.

## `advertiserIds` (type: `array`):

Deliver only ads of these Revcontent advertiser ids (whole numbers, as in the advertiserId column).

## `landingDomains` (type: `array`):

Deliver only ads whose landing address is on one of these domains or a sub domain of one. Only newer Revcontent boxes state a landing address; ads of older boxes never match this filter.

## `mediaTypes` (type: `array`):

Deliver only ads of these media types: image, animated (a gif) or video.

## `saveImages` (type: `boolean`):

Save each delivered ad's image file into the run's key-value store; the row gives its key and address (imageFileKey, imageFileUrl). One Image file event per saved image, charged only with the ad's own Ad event. Default false.

## `videoScenes` (type: `boolean`):

For every delivered ad with a video: download the video file and read its scene cuts (the seconds where it cuts to a new shot) and each shot's motion (0 to 1), from ffmpeg's scene scores inside the run. One Scene list event per video whose scenes were read, charged only with the ad's own Ad event. Every ad with a video gets its duration, sound track and picture size free anyway. Default false.

## `advertiserSummary` (type: `boolean`):

At the end of the run, one free advertiser row per Revcontent advertiser id of the delivered ads: its brands, campaigns, landing domains, sites, exit countries, media types and ad count. Default false.

## `includeRawData` (type: `boolean`):

Add Revcontent's own item to each ad row (rawItem): its descriptive fields only, never the click link, the event trackers or the request tokens. Default false.

## `runTag` (type: `string`):

A label of up to 100 letters, digits, spaces and . \_ , - : # ( ) / + copied onto every ad, coverage and advertiser row (to tell runs apart in one sheet).

## `memoryName` (type: `string`):

Give scheduled runs one name and each ad is delivered and charged once for that name: later runs deliver only ads the memory has not seen. Ads the memory knows are counted in the coverage rows, free. Letters, digits, spaces and . \_ , - : # ( ), up to 100 characters.

## `includeKnownAds` (type: `boolean`):

With a memory name: deliver each ad the memory already holds once per run as a free known_ad row, with the day the memory first delivered it and the days since, so you see which ads keep running. Default false.

## `resetMemory` (type: `boolean`):

Forget every ad the named memory knows before this run, so every ad counts as new again.

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

Leave as is for the Actor's own exits (the United States from Apify's US addresses, other countries from residential exits there). Group RESIDENTIAL reads every country, the United States included, from residential exits. A datacenter group reads the United States through it. Your own proxy URLs read every call through them (an answer served for another country than the one asked is not delivered). Apify Proxy turned off reads only the United States, from the container's own address.

## `includePersonalData` (type: `boolean`):

Off by default. Off, an e-mail address in the brand (brandName on ad rows, brandNames on advertiser rows, provider and brand in the raw item of includeRawData) is replaced by "(e-mail address hidden)" and the row's personalDataMasked is true (as in every earlier version on the rows; in the raw item since 2026-10-19). On, the brand is delivered exactly as Revcontent serves it, e-mail addresses included (the raw item too), and the brand and keyword filters compare that brand. You are responsible for a lawful use of personal data, GDPR included.

## Actor input object example

```json
{
  "countries": [
    "US"
  ],
  "sitesPerCountry": 3,
  "topUpWithOtherSites": true,
  "maxAds": 20,
  "maxCallsPerSite": 4,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "includePersonalData": 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 = {
    "countries": [
        "US"
    ],
    "sitesPerCountry": 3,
    "topUpWithOtherSites": true,
    "maxAds": 20,
    "maxCallsPerSite": 4,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation_craft/revcontent-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 = {
    "countries": ["US"],
    "sitesPerCountry": 3,
    "topUpWithOtherSites": True,
    "maxAds": 20,
    "maxCallsPerSite": 4,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("automation_craft/revcontent-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 '{
  "countries": [
    "US"
  ],
  "sitesPerCountry": 3,
  "topUpWithOtherSites": true,
  "maxAds": 20,
  "maxCallsPerSite": 4,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call automation_craft/revcontent-ads-scraper --silent --output-dataset

```

## MCP server setup

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