{
  "openapi": "3.0.1",
  "info": {
    "title": "Google Ads Transparency Scraper — full ad copy + image OCR",
    "description": "Every ad an advertiser runs on Google, with the real copy: headline, body, CTA, display and landing URLs, plus {KeyWord:...} templates and run dates. Image ads are read by a vision model, not Tesseract. Political mode adds spend and impressions. Search by domain, brand or ID. No login.",
    "version": "0.1",
    "x-build-id": "ai6HGSL9EibYquLPF"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/hyperbach~google-ads-transparency-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-hyperbach-google-ads-transparency-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/hyperbach~google-ads-transparency-scraper/runs": {
      "post": {
        "operationId": "runs-sync-hyperbach-google-ads-transparency-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/hyperbach~google-ads-transparency-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-hyperbach-google-ads-transparency-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": {
          "domains": {
            "title": "Advertiser domains",
            "type": "array",
            "description": "Domains to pull ads for, e.g. `nike.com`. Returns every verified advertiser matching that domain — a brand often runs under several (Nike advertises as both `Nike Retail BV` and `Nike, Inc.`).",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "searchTerms": {
            "title": "Brand / keyword searches",
            "type": "array",
            "description": "Brand or company name, e.g. `Nike`. Resolved to the matching verified advertisers first, then their ads are pulled — the ad search itself matches domains, not names, so a bare name would otherwise return nothing. Use `maxAdvertisersPerSearchTerm` to control how many matches are followed.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "advertiserIds": {
            "title": "Advertiser IDs",
            "type": "array",
            "description": "Exact advertiser IDs, e.g. `AR18378488041124659201` — the `AR...` value in an advertiser's Ads Transparency Center URL. Use this when you want one specific advertiser and nothing else.",
            "items": {
              "type": "string",
              "pattern": "^AR[0-9]+$"
            },
            "default": []
          },
          "region": {
            "title": "Region",
            "pattern": "^([A-Za-z]{2}|[Aa][Nn][Yy][Ww][Hh][Ee][Rr][Ee]|[Aa][Ll][Ll]|[Gg][Ll][Oo][Bb][Aa][Ll]|[0-9]+)$",
            "type": "string",
            "description": "Two-letter country code for the country the ads were shown in, e.g. `US`, `GB`, `DE`, `ES`, `IN`. Ads are published per country: the same advertiser returns different creatives in different regions. Use `anywhere` to search every country at once — the same thing `region=anywhere` does in a Transparency Center URL. `anywhere` covers scraping ads by domain, advertiser id or URL; `searchTerms`, `resultType: advertisers` and `politicalAds` need a real country, because Google's lookup and stats endpoints return nothing without one.",
            "default": "US"
          },
          "resultType": {
            "title": "Return",
            "enum": [
              "ads",
              "advertisers"
            ],
            "type": "string",
            "description": "`ads` returns one record per ad creative. `advertisers` returns one record per verified advertiser matching your domains or search terms — use it to discover which advertiser entities a brand runs under before pulling their ads.",
            "default": "ads"
          },
          "startDate": {
            "title": "Shown on or after",
            "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$",
            "type": "string",
            "description": "`YYYY-MM-DD`. Keeps ads whose run overlaps this date or later — an ad that started years ago and is still running counts, because it is still running."
          },
          "endDate": {
            "title": "Shown on or before",
            "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$",
            "type": "string",
            "description": "`YYYY-MM-DD`. Keeps ads whose run overlaps this date or earlier."
          },
          "adFormats": {
            "title": "Ad formats",
            "type": "array",
            "description": "Keep only these formats. Empty means all. Google returns text and video ads identically, so selecting either turns on the ad-copy fetch — that is the only thing that tells them apart.",
            "items": {
              "type": "string",
              "enum": [
                "text",
                "image",
                "video"
              ]
            },
            "default": []
          },
          "onlyAdsWithCopy": {
            "title": "Only ads with copy",
            "type": "boolean",
            "description": "Skip ads that carry no text at all — image creatives, and the occasional preview the source refuses to serve. Records that are skipped are never stored and never charged for, so you only pay for rows that carry the copy.",
            "default": false
          },
          "includeAdCopy": {
            "title": "Include full ad copy",
            "type": "boolean",
            "description": "Follow each ad's creative preview and extract the real headline, body text, display URL and the advertiser's `{KeyWord:...}` insertion templates. Turn off for a faster, metadata-only run.",
            "default": true
          },
          "maxAds": {
            "title": "Max ads",
            "minimum": 0,
            "type": "integer",
            "description": "Stop after this many ads in total, across every search. 0 means no limit.",
            "default": 0
          },
          "maxAdsPerTarget": {
            "title": "Max ads per search",
            "minimum": 0,
            "type": "integer",
            "description": "Cap each domain, search term, or advertiser ID separately. Without this, one prolific advertiser can consume the whole `maxAds` budget and the searches after it return nothing. 0 means no per-search cap.",
            "default": 0
          },
          "adCopyConcurrency": {
            "title": "Ad copy concurrency",
            "minimum": 1,
            "maximum": 16,
            "type": "integer",
            "description": "How many creative previews to fetch in parallel. Raise for speed, lower if you see throttling.",
            "default": 4
          },
          "requestDelaySecs": {
            "title": "Delay between pages",
            "minimum": 0,
            "type": "number",
            "description": "Seconds to wait between result pages. The source tolerates a steady pace far better than a burst.",
            "default": 0.3
          },
          "maxAdvertisersPerSearchTerm": {
            "title": "Max advertisers per search term",
            "minimum": 1,
            "maximum": 50,
            "type": "integer",
            "description": "How many matching advertisers to follow for each brand search term. A common name like `Nike` matches 150+ advertisers, most of them unrelated small businesses; the default takes the closest few.",
            "default": 5
          },
          "startUrls": {
            "title": "Start URLs",
            "type": "array",
            "description": "Paste Ads Transparency Center URLs — an advertiser page (`.../advertiser/AR...`) or a single creative (`.../advertiser/AR.../creative/CR...`). A creative URL narrows the run to that creative, and a `region` in the URL is used unless you set one explicitly.",
            "default": [],
            "items": {
              "type": "object",
              "required": [
                "url"
              ],
              "properties": {
                "url": {
                  "type": "string",
                  "title": "URL of a web page",
                  "format": "uri"
                }
              }
            }
          },
          "platforms": {
            "title": "Ad surfaces",
            "type": "array",
            "description": "Keep only ads shown on these Google surfaces. Empty means all. `search` and `shopping` share one filter at the source, so separating those two also needs the ad-copy fetch on.",
            "items": {
              "type": "string",
              "enum": [
                "search",
                "shopping",
                "display",
                "youtube"
              ]
            },
            "default": []
          },
          "creativeIds": {
            "title": "Creative IDs",
            "type": "array",
            "description": "Return only these creatives (`CR...`). Pair with `advertiserIds` or a creative URL in `startUrls`: the source has no by-creative lookup, so the advertiser's ads are paged until every requested creative is found.",
            "items": {
              "type": "string",
              "pattern": "^CR[0-9]+$"
            },
            "default": []
          },
          "onlyNewAds": {
            "title": "Only ads not seen before",
            "type": "boolean",
            "description": "Skip creatives delivered by previous runs that used the same `stateStoreName`. Skipped ads are never fetched, never returned and never charged — a weekly monitoring run pays only for what actually changed.",
            "default": false
          },
          "stateStoreName": {
            "title": "Monitoring store name",
            "type": "string",
            "description": "Named key-value store holding the creative IDs already delivered, so `onlyNewAds` can tell new from old across runs. Use one name per thing you monitor, e.g. `ads-monday-us`."
          },
          "resumeCursor": {
            "title": "Resume cursor",
            "type": "string",
            "description": "Continue paging from where an earlier run stopped. Paste the `RESUME_CURSOR` value from that run's key-value store. It is Google's own paging position — not a credential, and it grants no access to anything."
          },
          "includeRawData": {
            "title": "Include raw source record",
            "type": "boolean",
            "description": "Add the source's own untouched record to each row as `raw`, for callers who would rather map the fields themselves.",
            "default": false
          },
          "politicalAds": {
            "title": "Political ads (with spend and impressions)",
            "type": "boolean",
            "description": "Return political and election ads instead of ordinary ones. These carry what commercial ads never do: how much was spent on each creative and how many times it was shown, both as the ranges Google publishes. Note this is a filter — with it on, only political ads come back.",
            "default": false
          },
          "cacheStoreName": {
            "title": "Cache store",
            "type": "string",
            "description": "Named key-value store holding ad copy already extracted, so the same creative is never fetched twice — across your runs and over time. Ad creatives never change once published, so cached copy is served for ever; campaign statistics expire on the TTL below. Clear the field to disable caching.",
            "default": "gads-cache"
          },
          "cacheTtlHours": {
            "title": "Cache TTL (hours)",
            "minimum": 1,
            "type": "integer",
            "description": "How long slow-moving entries stay valid — campaign statistics and advertiser lookups. Extracted ad copy ignores this and is kept for ever, because a creative's content cannot change.",
            "default": 24
          },
          "removedAds": {
            "title": "Removed ads (Europe)",
            "type": "boolean",
            "description": "Return Google's Europe-wide feed of ads it has taken down, newest first, with the policy decision date and what each ad ran for before removal. This is a single global feed: advertiser, domain and region filters do not apply to it.",
            "default": false
          },
          "ocrImageAds": {
            "title": "Read text inside image ads (OCR)",
            "type": "boolean",
            "description": "Image creatives carry their words in the pixels and have no text field at all — on a typical advertiser they are most of the result set. Turn this on to read them with a vision model. Adds roughly two seconds per image, and is charged only for images that actually yielded text.",
            "default": false
          },
          "openaiApiKey": {
            "title": "OpenAI API key",
            "type": "string",
            "description": "Optional. The Actor uses its own model access by default and bills you a flat fee per image read. Supply your own OpenAI key only if you would rather the model usage went to your account."
          },
          "ocrConcurrency": {
            "title": "OCR concurrency",
            "minimum": 1,
            "maximum": 32,
            "type": "integer",
            "description": "How many image creatives to read at once when `ocrImageAds` is on. Separate from `adCopyConcurrency`, which paces requests to Google: OCR calls a different service, and it is network-bound, so it scales with concurrency (measured 0.6 to 3.9 images/second going from 1 to 16). Lower it only if you hit your own provider's rate limit.",
            "default": 12
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}