Apple Ad Repository Scraper avatar

Apple Ad Repository Scraper

Pricing

Pay per event

Go to Apify Store
Apple Ad Repository Scraper

Apple Ad Repository Scraper

Query Apple's official EU DSA Ad Repository API for every App Store ad Apple served an app or developer, per country — creative assets, targeting flags, impression dates. Give an app/developer name or known App Store id. No login, no API key.

Pricing

Pay per event

Rating

0.0

(0)

Developer

DevilScrapes

DevilScrapes

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

5 hours ago

Last modified

Share


🎯 What this scrapes

Under the EU Digital Services Act (Article 39), Apple is legally required to publish every App Store ad it delivered to EU users in a public Ad Repository. This Actor turns that repository into a queryable dataset: give it an app or developer name (or a known App Store id if you already have one) and it resolves the entity, then pulls every ad Apple served for it — per EU country, with the creative assets, targeting flags, and impression dates attached — instead of you hand-paging Apple's own web UI one app at a time.

Batch multiple apps or developers in a single run. Each target is fault-isolated — one app with zero ads or a temporary hiccup never sinks the others.

🔥 What we handle for you

  • 🛡️ Browser fingerprint rotationcurl-cffi impersonates real Chrome / Firefox TLS handshakes on every request.
  • 🔁 Retries with exponential backoff on 408 / 429 / 503 — up to 5 attempts per page, Retry-After honoured.
  • 🔎 Two-stage resolution — hand us a name and we resolve it to the right App Store entity ourselves, or skip straight to an ad-list query if you already know the id.
  • 📄 Real pagination past Apple's 50-item page size, up to the cap you set.
  • 🧊 Clean, typed dataset rows — Pydantic-validated, ISO-8601 timestamps, stable ids, JSON / CSV / Excel export straight from the Apify Console.
  • 💰 Pay-Per-Event pricing — you only pay for ad rows that hit your dataset. No data, no charge.

💡 Use cases

  • ASO agencies tracking which App Store ad creatives a client or rival is currently running in the EU.
  • Competitive intel — see exactly what formats, copy, and targeting a rival app is using, per country.
  • Ad-tech and policy research using Apple's own DSA transparency disclosures as a structured dataset.
  • Periodic monitoring — schedule a run and diff successive pulls to catch new creative launches.

⚙️ How to use it

  1. Click Try for free at the top of the page.
  2. Enter one or more app/developer names in entityNames, or known App Store ids in entities — at least one of the two is required.
  3. Optionally narrow countryOrRegions and datePreset, or leave the defaults.
  4. Click Start. Output streams into the run's dataset as each target resolves.
  5. Export from Storage → Dataset as JSON, CSV, or Excel — or fetch via the API.

📥 Input

FieldTypeRequiredDefaultNotes
entityNamesarrayno*[]App/developer names, resolved via Apple's own entity search.
entitiesarrayno*[]Known {id, type} pairs — skips name resolution.
countryOrRegionsarrayno[]ISO alpha-2 EU codes. Empty = every EU country Apple's own country endpoint returns, fetched live.
datePresetstringno"LAST_90_DAYS"LAST_90_DAYS / LAST_180_DAYS / LAST_YEAR.
maxItemsPerQueryintegerno500Cap on ad rows collected per resolved target.
proxyConfigurationobjectno{"useApifyProxy": false}Apify Proxy routing — off by default, see Limitations.

* At least one of entityNames / entities must be populated — validated before any charge fires.

Example input

{
"entityNames": ["Duolingo"],
"entities": [{"id": 570060128, "type": "APP"}],
"countryOrRegions": ["DE", "FR", "IT", "ES", "NL"],
"datePreset": "LAST_YEAR",
"maxItemsPerQuery": 120
}

📤 Output

Every row is one ad, in one country — the API itself scopes each record to a single countryOrRegion, so no extra fan-out is needed on our end.

FieldTypeNotes
adIdstringApple's stable ad identifier.
appId / appNameinteger / stringApp Store id and name shown in the ad.
developerId / developerName / legalNameinteger / string / stringAdvertiser identity, including the DSA-disclosed legal entity name.
placement / format / subFormatstringWhere and how the ad ran, e.g. APPSTORE_SEARCH_RESULTS / "Icon + Asset Ad".
countryOrRegionstringEU country this row's impressions were served in.
firstImpressionDate / lastImpressionDatestringDate range Apple recorded impressions for this ad, in this country.
adBannerSubtitle / adBannerPrimaryCategory / adBannerShortDescription / adBannerPromotionalTextstringAd banner creative text fields.
adBannerInAppPurchases / adBannerEditorialBadgebooleanAd banner disclosure flags.
adAssetPictureUrls / adAssetVideoUrls / appIconVariationsarrayCreative asset URLs — empty list when none, never null.
audienceAgeTarget / audienceGenderTarget / audienceLocationTarget / audienceCustomerTypeTargetbooleanWhich audience-targeting dimensions this ad used.
dataEndDatestringApple's own data-freshness cutoff for this query — see Limitations.
searchedEntityId / searchedEntityType / searchedEntityNameinteger / string / stringThe resolved target this row came from.
scrapedAtstringISO-8601 UTC timestamp when the row was scraped.

Example output

{
"adId": "a1b2c3",
"appId": 570060128,
"appName": "Duolingo: Language Lessons",
"developerName": "Duolingo",
"placement": "APPSTORE_SEARCH_RESULTS",
"format": "Icon + Asset Ad",
"countryOrRegion": "DE",
"firstImpressionDate": "2026-06-01",
"lastImpressionDate": "2026-08-30",
"adBannerSubtitle": "Lerne kostenlos",
"adBannerPrimaryCategory": "Education",
"adBannerInAppPurchases": true,
"adAssetPictureUrls": ["https://is5-ssl.mzstatic.com/.../asset1.png"],
"audienceLocationTarget": true,
"dataEndDate": "2026-09-14",
"searchedEntityId": 570060128,
"searchedEntityType": "APP",
"searchedEntityName": "Duolingo",
"scrapedAt": "2026-09-21T00:00:00Z"
}

💰 Pricing

Pay-Per-Event — you pay only when these events fire:

EventUSDWhat it is
actor-start$0.20One-off warm-up charge per run
ad-result$0.006Charged once per ad row (one ad in one country) written to the dataset

Example: 1 000 ad rows costs $0.20 start + 1 000 × $0.006 = $6.20 total. No subscription, no minimum, no card to start — Apify gives every new account $5 of free credit.

🚧 Limitations

  • EU-only by design, not by weakness. The Ad Repository exists because the EU's Digital Services Act mandates it — it covers App Store ads shown to EU users only. That's precision, not a gap: it's the exact scope Apple's legal disclosure obligation covers.
  • Apple's own data lags ~7 days. Every row carries dataEndDate, the cutoff Apple itself publishes for that query — so you always know exactly how fresh the data is instead of guessing. This is Apple's documented freshness window, not something we can shrink.
  • Two endpoints are deliberately out of scope for v1: per-ad locale/icon variations and Apple's advertising-restrictions endpoint. Both are real, sellable datasets in their own right — documented as follow-ups, not silently dropped.
  • No proxy is used by default (proxyConfiguration.useApifyProxy: false) — live wire probes found zero anti-bot surface on this API. You can opt into a named Apify Proxy group yourself if that ever changes.

❓ FAQ

Is this legal?

Yes — the Ad Repository is Apple's own public disclosure, published because EU law requires it. We only fetch what Apple already makes publicly queryable.

Why do I need both entityNames and entities?

You don't — either alone works. entityNames is the convenient path (we resolve the name to Apple's id for you); entities skips that lookup if you already know the numeric App Store id and entity type.

Why is dataEndDate a few days behind today?

That's Apple's own freshness cutoff for the Ad Repository, not a delay we introduce — we surface it on every row so you always know exactly how current your pull is.

How do I export to Sheets?

After the run, click Storage → Dataset → Export and pick CSV. Google Sheets imports it directly.

💬 Your feedback

Spotted a bug, hit a weird edge case, or need a new field? Open an issue on the Actor's Issues tab on Apify Console — we ship fixes weekly and we read every report.