
TikTok Shop Scraper
scrape.ly/store/shelfbright/tiktok-shop-scraperE-commerceSocial media
1 monthly user

Extract public ads from the Meta Ad Library by Facebook page, keyword, or ad-library URL. Returns creative, dates, platforms, delivery status, and optional page transparency.
Pull public ads from the Meta Ad Library without a Facebook login. Give it a Facebook page, a keyword search, or a full ad-library link and get back the creative, dates, platforms, and delivery status for every ad, ready to export as JSON, CSV, or Excel. Ads cost $3.50 per 1,000.
The actor reads the same public library anyone can open in a browser, so there are no cookies, accounts, or tokens to manage.
nike, or filtered ad-library links.| Field | Type | Description |
|---|---|---|
startUrls | array | Facebook page URL, page slug, or Meta Ad Library URL. Filters already in a library URL are kept. |
resultsLimit | integer | Maximum ads saved per URL. Default 10. |
activeStatus | string | "" (all), active, or inactive. Used when the URL does not already set it. |
sorting | string | "", total_impressions, or relevancy_monthly_grouped. Used when the URL does not set it. |
onlyAdsNewerThan | string | Keep ads started on or after this day. YYYY-MM-DD or a relative value like 7 days. |
onlyAdsOlderThan | string | Keep ads started on or before this day. Same formats. |
onlyTotal | boolean | One row per URL with the total count and the first page of ads under results. |
includeAboutPage | boolean | Add page about text, owner, admin locations, and history on page searches. |
isDetailsPerAd | boolean | Add an ad_details object per ad. |
enrichWithEcommerceData | boolean | Follow landing URLs and attach ecommerceData. Charged per product URL. |
proxyConfiguration | object | Proxy settings. Residential is the default. |
{
"startUrls": [
{
"url": "https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=ALL&is_targeted_country=false&media_type=all&search_type=page&view_all_page_id=15087023444"
}
],
"resultsLimit": 10,
"proxyConfiguration": {
"useScrapelyProxy": true,
"scrapelyProxyGroups": ["RESIDENTIAL"]
}
}
Each ad is one dataset row.
| Field | Description |
|---|---|
inputUrl | The URL that was searched. |
pageName, pageID | Advertiser page name and id. |
adArchiveID | Ad Library archive id. |
isActive | Whether the ad is still running. |
startDateFormatted, endDateFormatted | Start and end time in UTC. |
publisherPlatform | Platforms where the ad ran. |
snapshot | Creative: body text, title, call to action, cards, images, videos, link. |
pageInfo | Page record from the search, with transparency when requested. |
ad_details | Detail view per ad, when enabled. |
ecommerceData | Product name, price, and image from landing pages, when enabled. |
totalCount, results | Total ads and nested first page, on total-count rows. |
spend, reachEstimate | Empty on ordinary commercial ads. |
A trimmed item from a real run:
{
"adArchiveID": "3951220848520194",
"pageID": "380039845369159",
"pageName": "SHEIN",
"isActive": true,
"startDateFormatted": "2026-07-26T07:00:00.000Z",
"endDateFormatted": "2026-10-13T07:00:00.000Z",
"publisherPlatform": ["FACEBOOK", "INSTAGRAM"],
"inputUrl": "https://www.facebook.com/SHEINOFFICIAL",
"spend": null,
"reachEstimate": null,
"snapshot": {
"pageName": "SHEIN",
"pageProfileUri": "https://facebook.com/SHEINOFFICIAL",
"pageCategories": ["Clothing (Brand)"],
"pageLikeCount": 39137622,
"displayFormat": "DPA",
"ctaText": "Shop now",
"title": "{{product.name}}",
"body": { "text": "Eleve seu visual com nossa seleção criteriosa de sapatos da moda" },
"cards": [
{
"title": "Tênis Masculino Branco Gelo Chunky Para Basquete Corrida…",
"ctaType": "SHOP_NOW",
"caption": "m.shein.com",
"linkUrl": "https://br.shein.com/ark/default?scene=1&…"
}
]
}
}
Catalog and dynamic ads store template text such as {{product.name}}. That is the copy Meta keeps in the library. A URL that fails (invalid, page not found, blocked) saves no row and is never charged: it is listed with the reason under failedInputs in the run's OUTPUT record and in the status message, and ads already collected stay in the dataset.
| Event | Price |
|---|---|
Ad (result-item) | $0.0035 ($3.50 per 1,000 ads) |
Product page (ecommerce-enrichment) | $0.002 |
Product pages are charged only when that option is on and a landing page returns a product name plus a price or image. When an ad's products would go over your maximum charge, the ad keeps only the products the remaining budget pays for, is charged for exactly those, and is marked truncatedAtChargeLimit: true; the run then stops.
Worked example: a 10-ad run costs 10 x $0.0035 = $0.035 in event fees. Platform usage (compute and proxy) is billed on top at the usual rates; the default residential proxy is $2 per GB, and ads are light (about 3 MB per 1,000 ads, under one cent). A 10-ad run costs about $0.036 in total, and 1,000 ads about $3.51 plus compute.
No. The actor uses the public ad library only.
It reads public pages that anyone can open. You are responsible for how you use the data and for following the rules that apply to you.
Meta does not publish spend for a normal commercial ad. Political and social-issue ads include a range.
Yes. Country, keyword, platforms, media type, page id, and sort in the URL are sent with the search. Date and media filters are checked again on the saved ads, because the library sometimes returns a wider set than the URL asked for.
The run uses residential exits by default and retries each request on a fresh exit. If you choose the datacenter pool and it is blocked, the run switches to a residential exit. Rows saved before a later page fails are kept, and the run's status message says where it stopped.
Yes. Schedule runs, start them through the API, and read the dataset in any export format.
If you are moving from a similar Ad Library actor on another platform, paste the same library URL into Page or ad library URLs.
Every field below can be set in the run form, passed through the API, or saved as a task. Unset fields fall back to the defaults shown.
startUrlsarrayRequiredPage or ad library URLs
Facebook page URL, page name, or a Meta Ad Library search URL. Filters already present in an ad library URL are kept.
resultsLimitintegerOptionaldefault 10Ads per URL
Maximum ads to save for each URL.
Narrow ads by status, sort, and the date the ad started.
activeStatusenumOptionaldefault ""Active status
Used when the ad library URL does not already set an active status. Page URLs use this field.
sortingenumOptionaldefault ""Sort
Used when the ad library URL does not already set a sort.
onlyAdsNewerThanstringOptionalAds started after
Keep ads whose start date is on or after this day. Use YYYY-MM-DD or a relative value such as 7 days.
onlyAdsOlderThanstringOptionalAds started before
Keep ads whose start date is on or before this day. Use YYYY-MM-DD or a relative value such as 1 year.
Extra fields and the total-count row. Each of these is off unless you enable it.
onlyTotalbooleanOptionaldefault falseTotal count only
Save one row per URL with the total ad count and the first page of ads nested inside it.
includeAboutPagebooleanOptionaldefault falsePage transparency
Add the page about text, confirmed owner, admin locations, and page history when the library publishes them.
isDetailsPerAdbooleanOptionaldefault falseAd detail view
Open each ad's detail record and add advertiser, Instagram, and transparency fields under ad_details.
enrichWithEcommerceDatabooleanOptionaldefault falseProduct pages
Follow each ad's landing URL and attach public product name, price, and image when the page publishes them. Charged per product URL.
proxyConfigurationobjectOptionaldefault {"useScrapelyProxy":true,"scrapelyProxyGroups":["RESIDENTIA…Proxy configuration
Residential exits are the default: the ad library refuses further result pages to datacenter addresses. Datacenter is still selectable; the run then switches those pages to a residential exit by itself.
Every run writes its results to a dataset. Preview it in the dashboard, then export it or read it through the API.
| Field | Type | Description |
|---|---|---|
| inputUrl | string | null | URL that was searched. |
| pageName | string | null | Name of the page that ran the ad. |
| pageID | string | null | Facebook page id. |
| adArchiveID | string | null | Ad Library archive id. |
| isActive | boolean | null | Whether the ad is still running. |
| startDateFormatted | string | null | Ad start time in UTC. |
| endDateFormatted | string | null | Ad end time in UTC. |
| publisherPlatform | array | null | Platforms where the ad ran. |
| snapshot | object | null | Creative snapshot: copy, call to action, cards, images, and videos. |
| pageInfo | object | null | Page record returned with the search, including transparency when requested. |
| ad_details | object | null | Detail view for one ad, when ad detail view is enabled. |
| totalCount | number | null | Total ads reported for the search. Set on total-count rows. |
| results | array | null | Ads nested inside a total-count row. |
| ecommerceData | array | null | Product name, price, and image read from landing pages. |
| truncatedAtChargeLimit | boolean | Present (true) when the ad's ecommerceData was cut to what the run's maximum charge still paid for. |
You pay for the events the actor reports, such as each result or page it produces. Platform usage is included in the event prices.
| Event | Charged when | Price |
|---|---|---|
| Product page | One landing page that returned a public product name and a price or image. | $0.002 |
| Ad | One ad saved from the Meta Ad Library. | $0.0035 |
Run this actor from your own code. Swap in your API token and the examples work as-is.
import { ScrapelyClient } from 'scrapely-client'
const client = new ScrapelyClient({ token: process.env.SCRAPELY_TOKEN })
// Start the actor and wait for the run to finish.
const run = await client.actor('echofield/facebook-ads-scraper').call({
"startUrls": [
{
"url": "https://www.facebook.com/ads/library/?active_status=active&ad_type=all&country=ALL&is_targeted_country=false&media_type=all&search_type=page&view_all_page_id=15087023444"
}
],
"resultsLimit": 10,
"activeStatus": "",
"sorting": "",
"onlyAdsNewerThan": "2024-01-01",
"onlyAdsOlderThan": "2024-12-31",
"proxyConfiguration": {
"useScrapelyProxy": true,
"scrapelyProxyGroups": [
"RESIDENTIAL"
]
}
})
// Read the dataset the run produced.
const { items } = await client.dataset(run.defaultDatasetId).listItems()
console.log(items)Tokens live in your account settings. Keep them server-side: a token carries the full permissions of your account.
Connect the Scrape.ly MCP server once and your agent can run this actor as a tool. Pick your tool:
Fetch scrape.ly/agents.md and run echofield/facebook-ads-scraperPaste into Claude Code, Codex, Cursor or any AI agent. It signs you in once in the browser.
{
"mcpServers": {
"scrapely": {
"url": "https://api.scrape.ly/mcp?tools=actors,runs,storage,docs&actors=echofield/facebook-ads-scraper"
}
}
}No key in the file: your client opens the browser to sign you in the first time it connects.
Inputs the developer prepared for common jobs. Open one to see its input, then copy it to your account to run it as-is or adjust it.
Active ads plus the page's about details.
Ads from an Ad Library keyword search.
Ads enriched with linked e-commerce product info.
Scrape.ly gives you the infrastructure, the tooling, and the team to extract, process, and operationalize web data at any scale. Setup takes minutes. The advantage lasts forever.