{
  "openapi": "3.0.1",
  "info": {
    "title": "Facebook Ads Library Scraper — Meta Ad Library & Ad Spy",
    "description": "Facebook Ads Library & Meta Ad Library scraper (Facebook Ad Library, Meta ads, Instagram ads): search by keyword, advertiser, page or URL, spy on competitor ads, find winning ads (score, reach/day, days running), products & prices behind them, plus a new & stopped ads monitor. $0.60/1,000 ads.",
    "version": "0.1",
    "x-build-id": "ojfsZhxuvfpKJQ1ia"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/tactful_anvil~facebook-ads-library-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-tactful_anvil-facebook-ads-library-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/acts/tactful_anvil~facebook-ads-library-scraper/runs": {
      "post": {
        "operationId": "runs-sync-tactful_anvil-facebook-ads-library-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor and returns information about the initiated run in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/runsResponseSchema"
                }
              }
            }
          }
        }
      }
    },
    "/acts/tactful_anvil~facebook-ads-library-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-tactful_anvil-facebook-ads-library-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "inputSchema": {
        "type": "object",
        "properties": {
          "searchTerms": {
            "title": "Search terms (keywords or brands)",
            "type": "array",
            "description": "Keywords searched across all ad copy, e.g. \"running shoes\", \"crm software\", \"weight loss\". One Ad Library search per term. Ad Library URLs pasted here work too.",
            "items": {
              "type": "string"
            }
          },
          "advertisers": {
            "title": "Advertisers (name, @handle or page URL)",
            "type": "array",
            "description": "Every ad of these advertisers. Type a brand name (\"gymshark\"), an @handle, or paste facebook.com/<page> or instagram.com/<handle> — the Actor finds the page ID for you (exact match first, then verified / most-liked).",
            "items": {
              "type": "string"
            }
          },
          "pageIds": {
            "title": "Advertiser page IDs",
            "type": "array",
            "description": "Numeric Facebook page IDs to pull EVERY ad of one advertiser (find it in any Ad Library link as view_all_page_id=…). Profile URLs with ?id= also work.",
            "items": {
              "type": "string"
            }
          },
          "adLibraryUrls": {
            "title": "Ad Library URLs",
            "type": "array",
            "description": "Paste search URLs copied from facebook.com/ads/library — all filters in the URL (country, media type, platforms, dates, page) are applied as-is.",
            "items": {
              "type": "string"
            }
          },
          "adIds": {
            "title": "Single ads (Ad Library IDs)",
            "type": "array",
            "description": "Look up specific ads by their Ad Library ID (the number in facebook.com/ads/library/?id=…) or paste those links.",
            "items": {
              "type": "string"
            }
          },
          "excludeAdvertisers": {
            "title": "Exclude advertisers",
            "type": "array",
            "description": "Skip ads from these advertisers: exact page name, numeric page ID or facebook.com/<page> URL. Use it to leave out your own brand when you look for others using your brand name, or big brands when you build a list of smaller advertisers. Skipped ads are not charged.",
            "items": {
              "type": "string"
            }
          },
          "country": {
            "title": "Country",
            "type": "string",
            "description": "ISO-2 country where the ads were delivered (US, GB, DE, ID, BR…) or ALL for every country.",
            "default": "ALL"
          },
          "activeStatus": {
            "title": "Ad status",
            "enum": [
              "active",
              "inactive",
              "all"
            ],
            "type": "string",
            "description": "active = running now (default), inactive = stopped, all = both.",
            "default": "active"
          },
          "adType": {
            "title": "Ad category",
            "enum": [
              "all",
              "political_and_issue_ads",
              "housing_ads",
              "employment_ads",
              "financial_products_and_services_ads"
            ],
            "type": "string",
            "description": "all = every ad. The special categories carry extra transparency data (spend/impressions ranges for political ads).",
            "default": "all"
          },
          "mediaType": {
            "title": "Media type",
            "enum": [
              "all",
              "image",
              "video",
              "meme",
              "image_and_meme",
              "none"
            ],
            "type": "string",
            "description": "Filter by creative type.",
            "default": "all"
          },
          "platforms": {
            "title": "Platforms",
            "type": "array",
            "description": "Only ads shown on these platforms. Any of: facebook, instagram, messenger, audience_network, threads, whatsapp. Empty = all.",
            "items": {
              "type": "string"
            }
          },
          "languages": {
            "title": "Ad languages",
            "type": "array",
            "description": "ISO-639-1 codes of the ad copy language, e.g. en, es, de. Empty = all.",
            "items": {
              "type": "string"
            }
          },
          "exactPhrase": {
            "title": "Exact phrase",
            "type": "boolean",
            "description": "Search terms must appear as an exact phrase (Meta's \"keyword_exact_phrase\"). Off = any order.",
            "default": false
          },
          "sortBy": {
            "title": "Sort order",
            "enum": [
              "impressions",
              "newest"
            ],
            "type": "string",
            "description": "impressions = Meta's default, highest-impression ads first (best for finding winners). newest = most recently launched first (best for monitoring).",
            "default": "impressions"
          },
          "activeFrom": {
            "title": "Shown on or after",
            "type": "string",
            "description": "YYYY-MM-DD. Meta's date filter (\"impressions by date\"): only ads that were SHOWN on/after this day — they may have started earlier."
          },
          "activeTo": {
            "title": "Shown on or before",
            "type": "string",
            "description": "YYYY-MM-DD. Meta's date filter: only ads that were shown on/before this day."
          },
          "startedAfter": {
            "title": "Launched on or after",
            "type": "string",
            "description": "YYYY-MM-DD. Only ads whose first day (startDate) is on/after this day — i.e. NEW campaigns. Applied by this Actor after fetching; ads filtered out are not charged."
          },
          "startedWithinDays": {
            "title": "Launched within the last N days",
            "minimum": 0,
            "maximum": 3650,
            "type": "integer",
            "description": "Only ads whose first day (startDate) is within the last N days, counted from each run — the scheduler-friendly version of \"Launched on or after\" (a fixed date goes stale in a schedule). If both are set, the later date wins. Ads filtered out are not charged. 0 = off."
          },
          "maxAdsPerQuery": {
            "title": "Max ads per query",
            "minimum": 1,
            "maximum": 10000,
            "type": "integer",
            "description": "Stop each search/page/URL after this many unique ads. You pay only for ads delivered.",
            "default": 100
          },
          "maxAdsTotal": {
            "title": "Max ads in total (whole run)",
            "minimum": 1,
            "maximum": 1000000,
            "type": "integer",
            "description": "Optional budget cap: the run stops after this many ads in total across ALL searches, pages and links (each ad = one charged row). Empty = no total cap (each search still stops at Max ads per query)."
          },
          "minDaysActive": {
            "title": "Min days running (winning ads)",
            "minimum": 0,
            "maximum": 3650,
            "type": "integer",
            "description": "Only deliver ads that have been running at least this many days — long-running ads are the ones making money. Filtered ads are not charged. 0 = off.",
            "default": 0
          },
          "newWithinDays": {
            "title": "\"isNew\" window (days)",
            "minimum": 1,
            "maximum": 365,
            "type": "integer",
            "description": "An ad is flagged isNew=true when it started within this many days.",
            "default": 7
          },
          "onlyNewAds": {
            "title": "Monitor mode: only ads not seen before",
            "type": "boolean",
            "description": "Remembers every ad ID per query across runs (named key-value store). Schedule daily/weekly and receive — and pay for — only ads that are new since the last run. Best with Sort order = newest: each query stops as soon as it reaches last run's ads.",
            "default": false
          },
          "watchlistId": {
            "title": "Watchlist name (monitor memory)",
            "type": "string",
            "description": "Optional name for this monitor's memory, e.g. \"client-acme\". Each watchlist remembers its own ads, Meta's ad count per query and the last scan, so two clients watching the same brand never mix. With \"Monitor mode\" off, every ad is still delivered and flagged newSinceLastRun; RUN_SUMMARY lists ads stopped since the last run (free). Leave empty to keep the memory you already have."
          },
          "includeAdDetails": {
            "title": "Include ad details (EU/UK reach, targeting, payer)",
            "type": "boolean",
            "description": "Opens each ad's \"See ad details\": total reach and reach by country / age / gender (ads shown in the EU or UK), targeting age, gender and locations, payer & beneficiary, advertiser Instagram handle, followers and verification. Included in the price — turn off only for faster runs.",
            "default": true
          },
          "includeLandingPage": {
            "title": "Include landing page: product, price & store platform",
            "type": "boolean",
            "description": "Opens each ad's destination link once (duplicates and tracking parameters removed) and adds the product name, brand, price, compare-at price & discount %, currency, stock status, rating and the store platform (Shopify, WooCommerce, Wix, ClickFunnels …) to the row — read from the page's public product data. Included in the price (no extra charge). Read directly without a proxy: sites that block automated visits show landingStatus \"blocked\". Up to 300 landing pages per run (100 per site). Off by default.",
            "default": false
          },
          "saveCreatives": {
            "title": "Save ad creatives (images) to this run — $0.003 per file per started 5 MB",
            "type": "boolean",
            "description": "Meta's image and video links expire after a few days (see mediaExpiresAt). With this on, each delivered ad's image files (and video thumbnails) are downloaded straight from Meta's CDN into this run's key-value store, so they keep working: every row gets savedCreatives (key, link, size, type) and creativesSavedCount. Price: $0.003 per file per started 5 MB (an image under 5 MB = $0.003; $3 per 1,000 files), charged only after the file is saved and its ad row is in the dataset. Files that fail, are blocked, too large or over your max charge are free and listed in creativeErrors. The same file used by several ads is saved and charged once per run. Up to 10 files per ad. Becomes available once its price is active on this Actor; until then the run delivers the ads as usual and saves nothing. Off by default.",
            "default": false
          },
          "saveVideos": {
            "title": "Also save videos (with saveCreatives)",
            "type": "boolean",
            "description": "With saveCreatives: save the video file of video ads (HD, or SD when HD is larger than \"Max file size\") instead of its thumbnail. Videos are larger: $0.003 per started 5 MB, e.g. a 12 MB video = 3 × $0.003 = $0.009. Off by default.",
            "default": false
          },
          "maxCreativeMb": {
            "title": "Max file size (MB)",
            "minimum": 1,
            "maximum": 50,
            "type": "integer",
            "description": "With saveCreatives: files larger than this are not saved and not charged (creativeErrors \"too-large\"). 1-50 MB, default 25 — so one file costs at most 5 events ($0.015) at the default.",
            "default": 25
          },
          "includeAiAnalysis": {
            "title": "AI ad analysis (coming early December 2026)",
            "type": "boolean",
            "description": "Each delivered ad gets an aiAnalysis object written by Claude Haiku from its copy, CTA and (with includeLandingPage) landing product: one-line summary, hook, persuasion angle, offer and offer type, target audience, pain points, benefits, CTA intent, tone and sentiment — ready to filter and compare competitors' creative strategies. Price: $0.005 per analysed ad ($5 per 1,000), charged only after the ad row is in the dataset. Ads without any words (image-only), failures and ads over your max charge are free (aiAnalysis.status says why). Available on paid Apify plans. Becomes available once its price is active on this Actor; until then the run delivers the ads as usual and analyses nothing. Off by default.",
            "default": false
          },
          "aiAnalysisLanguage": {
            "title": "AI analysis language",
            "type": "string",
            "description": "Language code for the free-text fields of aiAnalysis (summary, hook, offer, audience, pain points, benefits): <code>en</code> (default), <code>es</code>, <code>de</code>, <code>id</code>… The label fields (angle, offerType, ctaIntent, tone, sentiment) stay in English so they can be filtered."
          },
          "aiDigest": {
            "title": "AI daily digest per competitor (coming early December 2026)",
            "type": "boolean",
            "description": "Schedule this Actor daily on your competitors and get, for every search / advertiser, ONE extra row (rowType \"ai-digest\") written by Claude Haiku: a headline, what changed since the last run, new angles, offers, hooks and formats, the most notable new ads (with links), what stopped, and 3 takeaways. A digest is written only when there is something to report (new or stopped ads, or the first run as a baseline) — quiet days cost nothing. Uses the monitor memory: set a watchlistId per client, or the digests keep their own watchlist \"ai-digest\". Price: $0.05 per digest, charged only after the digest row is in the dataset. Available on paid Apify plans. Becomes available once its price is active on this Actor; until then the run delivers the ads as usual and writes no digest. Off by default.",
            "default": false
          },
          "aiDigestLanguage": {
            "title": "AI digest language",
            "type": "string",
            "description": "Language code for the digest text: <code>en</code> (default), <code>es</code>, <code>de</code>, <code>id</code>… Quotes from the ads stay in their own language."
          },
          "countOnly": {
            "title": "Ad counts only (countOnly) — $0.004 per query × country",
            "type": "boolean",
            "description": "Instead of ad rows: ONE row per search × country with the number of ads Meta reports for your filters (adsTotal) — also when it is 0 — plus the ad formats and newest start date on Meta's first page. Only page 1 is opened: no paging, no ad details, no ad rows. $0.004 per row (query × country). With a watchlist name, each row also shows last run's count and the change. Becomes available once its price is active on this Actor; until then a countOnly run ends with 0 rows and charges nothing. Cheaper when you need the number for one country only: run without countOnly and maxAdsPerQuery = 1 ($0.0006 per query) — every ad row and RUN_SUMMARY carry the same total in queryAdsTotal.",
            "default": false
          },
          "countries": {
            "title": "Countries to count (countOnly only)",
            "type": "array",
            "description": "ISO-2 country codes (US, GB, DE, FR…, or ALL). Each search is counted in each of these countries: one row — and one $0.004 charge — per search × country. Empty = the Country field above. Ignored without countOnly.",
            "items": {
              "type": "string"
            }
          },
          "useResidentialForPaging": {
            "title": "Use residential proxy for paging (recommended)",
            "type": "boolean",
            "description": "Meta blocks paging (ads 31+) from datacenter IPs. With this on, the Actor pages through Apify's residential proxy automatically: about $0.035 of proxy traffic per 1,000 ads, billed by Apify on your plan. Page 1 and ad details always use the free direct route. Off = max ~30 ads per query.",
            "default": true
          },
          "proxyConfiguration": {
            "title": "Proxy configuration",
            "type": "object",
            "description": "Optional. Leave empty for the automatic setup above. Select RESIDENTIAL (or your own proxy URLs) to route everything through it."
          }
        }
      },
      "runsResponseSchema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "actId": {
                "type": "string"
              },
              "userId": {
                "type": "string"
              },
              "startedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "finishedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "status": {
                "type": "string",
                "example": "READY"
              },
              "meta": {
                "type": "object",
                "properties": {
                  "origin": {
                    "type": "string",
                    "example": "API"
                  },
                  "userAgent": {
                    "type": "string"
                  }
                }
              },
              "stats": {
                "type": "object",
                "properties": {
                  "inputBodyLen": {
                    "type": "integer",
                    "example": 2000
                  },
                  "rebootCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "restartCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "resurrectCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "computeUnits": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "options": {
                "type": "object",
                "properties": {
                  "build": {
                    "type": "string",
                    "example": "latest"
                  },
                  "timeoutSecs": {
                    "type": "integer",
                    "example": 300
                  },
                  "memoryMbytes": {
                    "type": "integer",
                    "example": 1024
                  },
                  "diskMbytes": {
                    "type": "integer",
                    "example": 2048
                  }
                }
              },
              "buildId": {
                "type": "string"
              },
              "defaultKeyValueStoreId": {
                "type": "string"
              },
              "defaultDatasetId": {
                "type": "string"
              },
              "defaultRequestQueueId": {
                "type": "string"
              },
              "buildNumber": {
                "type": "string",
                "example": "1.0.0"
              },
              "containerUrl": {
                "type": "string"
              },
              "usage": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "integer",
                    "example": 1
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "usageTotalUsd": {
                "type": "number",
                "example": 0.00005
              },
              "usageUsd": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "number",
                    "example": 0.00005
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}