{
  "openapi": "3.0.1",
  "info": {
    "title": "Facebook Ads Library Scraper - Meta Ad Library Monitoring",
    "description": "Monitor Facebook and Instagram competitor ads on a schedule. Every result comes back labelled new, ongoing, or ended against your previous runs, so you read what changed instead of the same list again. Up to 5 keywords, Page ID targeting, creatives, copy and CTA links. No Facebook login.",
    "version": "1.0",
    "x-build-id": "5Qy6DgVlcJcNggMfS"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/jy-labs~meta-ad-library-multi-search-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-jy-labs-meta-ad-library-multi-search-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/jy-labs~meta-ad-library-multi-search-scraper/runs": {
      "post": {
        "operationId": "runs-sync-jy-labs-meta-ad-library-multi-search-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/jy-labs~meta-ad-library-multi-search-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-jy-labs-meta-ad-library-multi-search-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",
        "required": [
          "keywords"
        ],
        "properties": {
          "keywords": {
            "title": "Search Keywords",
            "maxItems": 5,
            "type": "array",
            "description": "Keywords to search for ads (e.g., brand names, product names). Each keyword is processed sequentially. Pair with Page IDs below to narrow results to a specific advertiser's page — useful when multiple brands share the same keyword.",
            "items": {
              "type": "string"
            }
          },
          "pageIds": {
            "title": "Page IDs (optional)",
            "maxItems": 5,
            "type": "array",
            "description": "Optional. Provide the exact numeric view_all_page_id of an advertiser's Facebook Page. Each entry is matched by index to keywords — pageIds[0] applies to keywords[0], pageIds[1] to keywords[1], and so on. Leave an entry blank to use keyword-only search at that position. Find the Page ID by searching the advertiser in Meta Ad Library and copying the digits from view_all_page_id=XXXXXXXXX in the URL. Non-numeric values are rejected before browser work starts. Example: [\"\", \"123456789\"] skips Page ID for keywords[0] and restricts keywords[1] to page 123456789.",
            "items": {
              "type": "string",
              "pattern": "^\\d*$"
            }
          },
          "country": {
            "title": "Country",
            "enum": [
              "US",
              "GB",
              "DE",
              "FR",
              "NL",
              "IT",
              "ES",
              "SG",
              "CA",
              "AU",
              "JP",
              "IN",
              "BR",
              "MX",
              "KR",
              "TW",
              "HK",
              "TH",
              "VN",
              "ID",
              "PH",
              "MY",
              "ALL"
            ],
            "type": "string",
            "description": "Country whose Ad Library is searched. Defaults to US, the largest Meta ad market and the one the Actor is tuned against. This also selects the residential proxy exit country, so an unusual choice can be slower and occasionally rate-limited.",
            "default": "US"
          },
          "adType": {
            "title": "Ad Type",
            "enum": [
              "all",
              "political_and_issue_ads"
            ],
            "type": "string",
            "description": "Type of ads to search",
            "default": "all"
          },
          "activeStatus": {
            "title": "Active Status",
            "enum": [
              "all",
              "active",
              "inactive"
            ],
            "type": "string",
            "description": "Filter by ad active status",
            "default": "all"
          },
          "mediaType": {
            "title": "Media Type",
            "enum": [
              "all",
              "image",
              "meme",
              "video",
              "none"
            ],
            "type": "string",
            "description": "Filter by media type",
            "default": "all"
          },
          "startDateMin": {
            "title": "Start Date (From)",
            "type": "string",
            "description": "Filter ads that started running on or after this date. Leave empty for no minimum date filter."
          },
          "startDateMax": {
            "title": "Start Date (To)",
            "type": "string",
            "description": "Filter ads that started running on or before this date. Leave empty for no maximum date filter."
          },
          "sortBy": {
            "title": "Sort By",
            "enum": [
              "relevancy_monthly_grouped",
              "total_impressions"
            ],
            "type": "string",
            "description": "Sort order for search results. Relevance is Meta's own default ranking and returns the same results a plain Ad Library search does — keep it unless you specifically want the widest-reaching ads first.",
            "default": "relevancy_monthly_grouped"
          },
          "searchType": {
            "title": "Keyword Matching",
            "enum": [
              "exact_phrase",
              "unordered"
            ],
            "type": "string",
            "description": "How Meta matches a multi-word keyword.\\n\\n• Exact phrase (default) — the words must appear together, in order. Searching `Liquid Death` returns Liquid Death ads.\\n• Any word — Meta’s wide net: any of the words, anywhere, in any order. Searching `Liquid Death` also returns ads that merely say “liquid” in one line and “death” in another. Use it only when you want maximum recall and will filter afterwards.\\n\\nSingle-word keywords behave identically in both modes.",
            "default": "exact_phrase"
          },
          "maxResults": {
            "title": "Max Results",
            "minimum": 1,
            "maximum": 200,
            "type": "integer",
            "description": "Maximum number of results to collect per keyword. Counts ads by default; when “One result per advertiser” is set below, it counts distinct advertisers instead.",
            "default": 100
          },
          "dedupeBy": {
            "title": "One result per advertiser",
            "enum": [
              "none",
              "advertiser"
            ],
            "type": "string",
            "description": "Whether Max Results counts ads or advertisers.\n\n• Every ad (default) — one row per ad. A single heavy spender can fill the whole result set with its own creatives.\n• One ad per advertiser — Max Results counts **distinct advertisers**, so 200 results means 200 different accounts. The ad kept for each advertiser is its best keyword match, and an `advertiserAdCount` field reports how many ads that advertiser was running among the ads scanned. Deduplication spans the whole run, so an advertiser found under two keywords is still one row. Use it when you are prospecting for accounts running an offer rather than collecting creatives.",
            "default": "none"
          },
          "trackChanges": {
            "title": "Track changes between runs",
            "type": "boolean",
            "description": "Label every ad against what previous runs of this same search returned: adStatus (new/ongoing), isNew, firstSeenDate, lastSeenDate and runsSeen are added to each result. History is kept in a key-value store named 'meta-ad-monitor' inside your own account, so a scheduled run can report what your competitors started this week instead of repeating the same list.\n\nThis adds fields only — it never removes or filters results, so two runs of the same search return the same rows with different labels. To receive only what changed, use “Only return ads that are new since the last run” below.",
            "default": true
          },
          "onlyNewAds": {
            "title": "Only return ads that are new since the last run",
            "type": "boolean",
            "description": "Deliver only the ads this search has not returned before, instead of the full list every run. This is the option that makes a daily or weekly schedule read as a change feed: a run that finds nothing new returns nothing and costs you nothing in result charges.\n\nThe first run of a search returns everything, because everything genuinely is new. Change tracking is required and is switched on automatically when you enable this. Ads that are filtered out are still recorded in your history, so they are never re-reported as new later. If the history cannot be read, the run delivers every row rather than silently returning none.",
            "default": false
          },
          "monitorKey": {
            "title": "Monitoring stream name",
            "type": "string",
            "description": "Optional. Names the history stream. Leave empty and the stream is identified by the search itself (keywords, page IDs, country, ad type, status, media type), so a saved task on a schedule lines up automatically. Set it to keep separate histories for separate clients from one input."
          },
          "includeEndedAds": {
            "title": "Also report ads that stopped running",
            "type": "boolean",
            "description": "Emit an extra row (adStatus: 'ended') for each tracked ad that has been absent for two consecutive runs — the signal that a competitor retired a creative. Off by default because these rows are charged like any other result. Suppressed automatically when a run fails or completes only partially, since an ad missing from a broken run has not ended.",
            "default": false
          },
          "proxy": {
            "title": "Proxy Configuration",
            "type": "object",
            "description": "Proxy settings for accessing Meta Ad Library. RESIDENTIAL proxy is required — Facebook rate-limits GraphQL pagination from datacenter IPs, causing scroll to fail silently with zero new ads.",
            "default": {
              "useApifyProxy": true,
              "apifyProxyGroups": [
                "RESIDENTIAL"
              ]
            }
          },
          "requestHandlerTimeoutSecs": {
            "title": "Per-keyword Processing Timeout (seconds)",
            "minimum": 60,
            "maximum": 600,
            "type": "integer",
            "description": "Ceiling on per-keyword processing time across navigation, readiness checks, scrolling, and extraction. This is a ceiling, not a target — a keyword that finishes in 60 seconds still finishes in 60 seconds, and the Actor's own timeout is still divided across your keywords so one slow keyword cannot starve the rest. Large requests need the headroom: a 200-result run with One result per advertiser takes about 270 seconds of scrolling on its own. Lower it only if you want to cap how long any single keyword may take.",
            "default": 600
          },
          "relevanceMode": {
            "title": "Relevance Mode",
            "enum": [
              "balanced",
              "strict",
              "all"
            ],
            "type": "string",
            "description": "How strictly results must prove they match your keyword.\n\n• Balanced (default) — returns ads that show the keyword in a visible field first, then fills the remaining slots with partial matches and Meta's own ranked results until Max Results is met. Every row is labelled in the `matchedBy` field so you can filter afterwards.\n• Strict — only ads with a Page ID or a full visible keyword match. Highest precision, but for brands whose ad copy never spells the brand name out (e.g. slogan-only creatives) this can return almost nothing.\n• All — Meta's own ranking order, unfiltered and un-reranked.",
            "default": "balanced"
          },
          "includeUnverifiedMetaSearchResults": {
            "title": "Include Unverified Meta Search Results (deprecated)",
            "type": "boolean",
            "description": "Deprecated — use Relevance Mode instead. Enabling this is equivalent to Relevance Mode \"Balanced\". Leaving it off no longer forces strict filtering; set Relevance Mode to \"Strict\" for that.",
            "default": false
          },
          "blockMediaAssets": {
            "title": "Block image and video downloads",
            "type": "boolean",
            "description": "Skips downloading ad images, videos and fonts while scraping. The Actor still extracts every media URL, so output is unchanged — but the run transfers far less data through the proxy, which lowers your platform usage cost. Turn this off only if a search stops returning results.",
            "default": true
          },
          "debugMode": {
            "title": "Debug Mode",
            "type": "boolean",
            "description": "Opt in to storing a screenshot of the final search page as PAGE_SCREENSHOT in the run key-value store. The screenshot can contain visible ad content and should be enabled only for troubleshooting.",
            "default": false
          }
        }
      },
      "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
                  }
                }
              },
              "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}