{
  "data": {
    "id": "wrUve4WlpfpUTcaYq",
    "actId": "c4vabXjZcq0Eylrer",
    "userId": "IYgBDiXtHOijAaUel",
    "startedAt": "2026-10-27T12:00:00.374Z",
    "finishedAt": "2026-10-27T12:00:48.288Z",
    "status": "SUCCEEDED",
    "meta": {
      "origin": "CLI"
    },
    "stats": {
      "durationMillis": 47800,
      "runTimeSecs": 47.8,
      "computeUnits": 0.05311111111111111,
      "imageSizeBytes": 3143536128
    },
    "options": {
      "useCache": true,
      "betaPackages": false,
      "memoryMbytes": 4096,
      "diskMbytes": 8192
    },
    "createdByOrganizationMemberUserId": "QYo53EZkJk0prePWY",
    "exitCode": 0,
    "inputSchema": "{\n  \"title\": \"LinkedIn Ad Library Scraper Input\",\n  \"description\": \"Search the public LinkedIn Ad Library, scrape specific ads, or count matches. Every keyword, advertiser, payer, and company-ID group becomes its own search; country, date, sort, impression, and targeting filters apply to all searches.\",\n  \"type\": \"object\",\n  \"schemaVersion\": 1,\n  \"properties\": {\n    \"mode\": {\n      \"title\": \"Mode\",\n      \"type\": \"string\",\n      \"description\": \"What to collect: search the library, open specific ads, process pasted URLs, or count matches only.\",\n      \"editor\": \"select\",\n      \"default\": \"search\",\n      \"prefill\": \"search\",\n      \"enum\": [\n        \"search\",\n        \"adDetails\",\n        \"directUrls\",\n        \"count\"\n      ],\n      \"enumTitles\": [\n        \"Search the Ad Library\",\n        \"Specific ad IDs / detail URLs\",\n        \"Pasted Ad Library / company URLs\",\n        \"Count matches only\"\n      ]\n    },\n    \"searchTerms\": {\n      \"title\": \"Keywords\",\n      \"type\": \"array\",\n      \"description\": \"One or more keyword searches, e.g. 'AI' or 'cloud computing'. Each keyword is an independent search (union), not a combination.\",\n      \"editor\": \"stringList\",\n      \"items\": {\n        \"type\": \"string\"\n      },\n      \"default\": [],\n      \"example\": [\n        \"AI\",\n        \"cloud computing\"\n      ]\n    },\n    \"advertisers\": {\n      \"title\": \"Advertisers\",\n      \"type\": \"array\",\n      \"description\": \"Advertiser names (fuzzy accountOwner search) or LinkedIn company URLs. Each name is an independent search. Use companyIds for exact matching.\",\n      \"editor\": \"stringList\",\n      \"items\": {\n        \"type\": \"string\"\n      },\n      \"default\": [],\n      \"example\": [\n        \"Microsoft\",\n        \"Anthropic\"\n      ]\n    },\n    \"companyIds\": {\n      \"title\": \"LinkedIn Company IDs\",\n      \"type\": \"array\",\n      \"description\": \"Exact numeric LinkedIn company IDs (for example, Microsoft is 1035). Multiple IDs are OR-ed in one exact search. Company URLs are accepted too.\",\n      \"editor\": \"stringList\",\n      \"items\": {\n        \"type\": \"string\"\n      },\n      \"default\": [],\n      \"prefill\": [\n        \"1035\"\n      ],\n      \"example\": [\n        \"1035\",\n        \"3608\"\n      ]\n    },\n    \"companyUrls\": {\n      \"title\": \"Company URLs\",\n      \"type\": \"array\",\n      \"description\": \"LinkedIn company page URLs. The actor resolves each public page to its numeric organization ID and searches it exactly.\",\n      \"editor\": \"stringList\",\n      \"items\": {\n        \"type\": \"string\"\n      },\n      \"default\": [],\n      \"example\": [\n        \"https://www.linkedin.com/company/microsoft\"\n      ]\n    },\n    \"payer\": {\n      \"title\": \"Paid for by (payer)\",\n      \"type\": \"array\",\n      \"description\": \"Search ads by the legal entity that paid for them, e.g. 'Microsoft Corporation'. Each payer is an independent search.\",\n      \"editor\": \"stringList\",\n      \"items\": {\n        \"type\": \"string\"\n      },\n      \"default\": [],\n      \"example\": [\n        \"Microsoft Corporation\"\n      ]\n    },\n    \"advertiserMatch\": {\n      \"title\": \"Advertiser Name Match\",\n      \"type\": \"string\",\n      \"description\": \"Client-side precision for advertiser-name searches. Exact company IDs are never filtered. 'Starts with' removes partner-noise results while keeping names such as 'Microsoft in Business'.\",\n      \"editor\": \"select\",\n      \"default\": \"startsWith\",\n      \"enum\": [\n        \"any\",\n        \"startsWith\",\n        \"exact\"\n      ],\n      \"enumTitles\": [\n        \"Any match\",\n        \"Starts with\",\n        \"Exact name\"\n      ]\n    },\n    \"countries\": {\n      \"title\": \"Countries\",\n      \"type\": \"array\",\n      \"description\": \"ISO-3166 alpha-2 delivery country codes (US, GB, DE, ...) or ALL. Multiple codes are sent in one comma-separated filter.\",\n      \"editor\": \"stringList\",\n      \"items\": {\n        \"type\": \"string\"\n      },\n      \"default\": [],\n      \"example\": [\n        \"US\",\n        \"DE\"\n      ]\n    },\n    \"dateOption\": {\n      \"title\": \"Date Range\",\n      \"type\": \"string\",\n      \"description\": \"LinkedIn's date window. Use custom-date-range with startDate/endDate for an exact period (maximum 12 months back).\",\n      \"editor\": \"select\",\n      \"default\": \"last-30-days\",\n      \"prefill\": \"last-30-days\",\n      \"enum\": [\n        \"any-time\",\n        \"last-30-days\",\n        \"current-month\",\n        \"current-year\",\n        \"last-year\",\n        \"custom-date-range\"\n      ],\n      \"enumTitles\": [\n        \"Any time\",\n        \"Last 30 days\",\n        \"Current month\",\n        \"Current year\",\n        \"Last year\",\n        \"Custom date range\"\n      ]\n    },\n    \"startDate\": {\n      \"title\": \"Start Date\",\n      \"type\": \"string\",\n      \"description\": \"Start of a custom range (YYYY-MM-DD). Required when dateOption is custom-date-range.\",\n      \"editor\": \"textfield\",\n      \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2}$\"\n    },\n    \"endDate\": {\n      \"title\": \"End Date\",\n      \"type\": \"string\",\n      \"description\": \"End of a custom range (YYYY-MM-DD). Required when dateOption is custom-date-range.\",\n      \"editor\": \"textfield\",\n      \"pattern\": \"^\\\\d{4}-\\\\d{2}-\\\\d{2}$\"\n    },\n    \"sortOrder\": {\n      \"title\": \"Sort Order\",\n      \"type\": \"string\",\n      \"description\": \"Newest first or oldest first.\",\n      \"editor\": \"select\",\n      \"default\": \"newest\",\n      \"enum\": [\n        \"newest\",\n        \"oldest\"\n      ],\n      \"enumTitles\": [\n        \"Newest first\",\n        \"Oldest first\"\n      ]\n    },\n    \"impressionsMinValue\": {\n      \"title\": \"Minimum Impressions Value\",\n      \"type\": \"integer\",\n      \"description\": \"Lower bound of the impression range (EU transparency data only). LinkedIn requires both a minimum and a maximum value.\",\n      \"minimum\": 0,\n      \"maximum\": 1000000000,\n      \"editor\": \"number\"\n    },\n    \"impressionsMinUnit\": {\n      \"title\": \"Minimum Impressions Unit\",\n      \"type\": \"string\",\n      \"description\": \"Unit for the minimum impression value.\",\n      \"editor\": \"select\",\n      \"default\": \"none\",\n      \"enum\": [\n        \"none\",\n        \"thousand\",\n        \"million\"\n      ],\n      \"enumTitles\": [\n        \"Units\",\n        \"Thousands\",\n        \"Millions\"\n      ]\n    },\n    \"impressionsMaxValue\": {\n      \"title\": \"Maximum Impressions Value\",\n      \"type\": \"integer\",\n      \"description\": \"Upper bound of the impression range (EU transparency data only). Required together with the minimum value.\",\n      \"minimum\": 0,\n      \"maximum\": 1000000000,\n      \"editor\": \"number\"\n    },\n    \"impressionsMaxUnit\": {\n      \"title\": \"Maximum Impressions Unit\",\n      \"type\": \"string\",\n      \"description\": \"Unit for the maximum impression value.\",\n      \"editor\": \"select\",\n      \"default\": \"none\",\n      \"enum\": [\n        \"none\",\n        \"thousand\",\n        \"million\"\n      ],\n      \"enumTitles\": [\n        \"Units\",\n        \"Thousands\",\n        \"Millions\"\n      ]\n    },\n    \"targetingIncluded\": {\n      \"title\": \"Included Targeting Facets\",\n      \"type\": \"array\",\n      \"description\": \"Filters ads that target any of these categories (EU transparency data only). Values: LANGUAGE, LOCATION, AUDIENCE, DEMOGRAPHIC, COMPANY, EDUCATION, JOB, INTERESTS_AND_TRAITS.\",\n      \"editor\": \"stringList\",\n      \"items\": {\n        \"type\": \"string\"\n      },\n      \"default\": [],\n      \"example\": [\n        \"LANGUAGE\",\n        \"JOB\"\n      ]\n    },\n    \"targetingExcluded\": {\n      \"title\": \"Excluded Targeting Facets\",\n      \"type\": \"array\",\n      \"description\": \"Filters ads that exclude any of these categories (EU transparency data only). Values: LANGUAGE, LOCATION, AUDIENCE, DEMOGRAPHIC, COMPANY, EDUCATION, JOB, INTERESTS_AND_TRAITS.\",\n      \"editor\": \"stringList\",\n      \"items\": {\n        \"type\": \"string\"\n      },\n      \"default\": [],\n      \"example\": [\n        \"COMPANY\"\n      ]\n    },\n    \"includeDetails\": {\n      \"title\": \"Include Detail Pages\",\n      \"type\": \"boolean\",\n      \"description\": \"Open each ad's detail page for full copy, CTA, landing URL, video, payer, and EU transparency data. Adds one request per ad.\",\n      \"default\": true,\n      \"prefill\": true,\n      \"editor\": \"checkbox\"\n    },\n    \"decodeShortLinks\": {\n      \"title\": \"Decode Short Links\",\n      \"type\": \"boolean\",\n      \"description\": \"Resolve lnkd.in and similar short links to their final landing URL. Adds one request per short link.\",\n      \"default\": false,\n      \"editor\": \"checkbox\"\n    },\n    \"adIds\": {\n      \"title\": \"Ad IDs or Detail URLs\",\n      \"type\": \"array\",\n      \"description\": \"Numeric ad IDs or linkedin.com/ad-library/detail/... URLs. Used by mode adDetails.\",\n      \"editor\": \"stringList\",\n      \"items\": {\n        \"type\": \"string\"\n      },\n      \"default\": [],\n      \"example\": [\n        \"1611810664\"\n      ]\n    },\n    \"directUrls\": {\n      \"title\": \"Direct URLs\",\n      \"type\": \"array\",\n      \"description\": \"Pasted Ad Library search URLs, ad detail URLs, or LinkedIn company page URLs. Search filters are preserved.\",\n      \"editor\": \"requestListSources\",\n      \"default\": [],\n      \"example\": [\n        {\n          \"url\": \"https://www.linkedin.com/ad-library/search?keyword=AI&countries=US\"\n        }\n      ]\n    },\n    \"maxItems\": {\n      \"title\": \"Maximum Records\",\n      \"type\": \"integer\",\n      \"description\": \"Global cap on ads returned across all searches (1-4800). Each search can return at most 4,800 ads (200 pages of 24).\",\n      \"default\": 50,\n      \"prefill\": 3,\n      \"minimum\": 1,\n      \"maximum\": 4800,\n      \"editor\": \"number\"\n    }\n  },\n  \"required\": []\n}",
    "readme": "# LinkedIn Ad Library Keyword & Advertiser Scraper\r\n\r\nSearch the **public LinkedIn Ad Library** without an account, cookies, or a login. Collect paginated ads by keyword, advertiser name, payer, exact company ID, or a pasted Ad Library URL — then enrich each ad with its full copy, CTA, landing URL, video, paying entity, and the EU transparency block (run dates, impression range, country shares, and targeting).\r\n\r\nThe actor is built for competitor research, creative monitoring, and B2B ad intelligence. It reads the same public pages a logged-out visitor sees, so it works with zero credentials.\r\n\r\n## Modes\r\n\r\n| Mode | What it does | Inputs it uses |\r\n| --- | --- | --- |\r\n| `search` (default) | Builds one search per keyword / advertiser / payer / company-ID group, paginates it, dedupes by ad ID, and optionally opens every detail page. | `searchTerms`, `advertisers`, `companyIds`, `companyUrls`, `payer`, filters |\r\n| `adDetails` | Re-scrapes specific ads from their IDs or detail URLs. | `adIds`, `directUrls` (detail URLs) |\r\n| `directUrls` | Accepts pasted Ad Library search URLs, company URLs, and ad detail URLs. Search filters are preserved. | `directUrls` |\r\n| `count` | Returns the total number of matching ads per search, without pagination. | The same search inputs |\r\n\r\nEvery keyword, advertiser, payer, and company-ID group is an **independent search** (a union). Filters such as country, date, sort, impressions, and targeting apply to all of them.\r\n\r\n## Inputs\r\n\r\n| Input | Type | Default | Description |\r\n| --- | --- | --- | --- |\r\n| `mode` | Select | `search` | `search`, `adDetails`, `directUrls`, or `count`. |\r\n| `searchTerms` | String list | `[]` | Keyword searches. |\r\n| `advertisers` | String list | `[]` | Advertiser names (fuzzy) or LinkedIn company URLs. |\r\n| `companyIds` | String list | `[]` | Exact numeric LinkedIn company IDs; multiple IDs are OR-ed. URLs are accepted. |\r\n| `companyUrls` | String list | `[]` | Company page URLs, resolved to their numeric organization ID. |\r\n| `payer` | String list | `[]` | Legal entity that paid for the ad. |\r\n| `advertiserMatch` | Select | `startsWith` | Client-side precision for advertiser-name searches: `any`, `startsWith`, `exact`. |\r\n| `countries` | String list | `[]` | ISO-3166 alpha-2 codes (`US`, `GB`, `DE`) or `ALL`. Multiple codes are comma-joined. |\r\n| `dateOption` | Select | `last-30-days` | `any-time`, `last-30-days`, `current-month`, `current-year`, `last-year`, `custom-date-range`. |\r\n| `startDate` / `endDate` | String | — | Required for `custom-date-range` (YYYY-MM-DD, within the last 12 months). |\r\n| `sortOrder` | Select | `newest` | `newest` or `oldest`. |\r\n| `impressionsMinValue` / `impressionsMaxValue` | Integer | — | EU impression range. LinkedIn requires both values. |\r\n| `impressionsMinUnit` / `impressionsMaxUnit` | Select | `none` | `none`, `thousand`, or `million`. |\r\n| `targetingIncluded` / `targetingExcluded` | String list | `[]` | EU targeting facets: `LANGUAGE`, `LOCATION`, `AUDIENCE`, `DEMOGRAPHIC`, `COMPANY`, `EDUCATION`, `JOB`, `INTERESTS_AND_TRAITS`. |\r\n| `includeDetails` | Boolean | `true` | Open each ad's detail page for full copy, CTA, landing URL, video, payer, and EU data. |\r\n| `decodeShortLinks` | Boolean | `false` | Resolve `lnkd.in` and similar short links to the final landing URL. |\r\n| `adIds` | String list | `[]` | Ad IDs or detail URLs, for `adDetails`. |\r\n| `directUrls` | URL list | `[]` | Pasted Ad Library search/detail URLs or company URLs. |\r\n| `maxItems` | Integer | `50` | Global cap per run (1–4,800). |\r\n\r\n### Prefill\r\n\r\nThe default prefill is the smallest run with a reliable result: Microsoft's exact company ID, the last 30 days, three ads, and detail enrichment on.\r\n\r\n```json\r\n{\r\n  \"mode\": \"search\",\r\n  \"companyIds\": [\"1035\"],\r\n  \"dateOption\": \"last-30-days\",\r\n  \"includeDetails\": true,\r\n  \"maxItems\": 3\r\n}\r\n```\r\n\r\n### Example — keyword search, card data only\r\n\r\n```json\r\n{\r\n  \"searchTerms\": [\"AI\", \"machine learning\"],\r\n  \"countries\": [\"US\", \"DE\"],\r\n  \"dateOption\": \"last-30-days\",\r\n  \"includeDetails\": false,\r\n  \"maxItems\": 100\r\n}\r\n```\r\n\r\n### Example — exact advertiser with EU transparency\r\n\r\n```json\r\n{\r\n  \"companyIds\": [\"1035\"],\r\n  \"countries\": [\"DE\"],\r\n  \"dateOption\": \"last-year\",\r\n  \"includeDetails\": true,\r\n  \"maxItems\": 200\r\n}\r\n```\r\n\r\n### Example — re-scrape specific ads\r\n\r\n```json\r\n{\r\n  \"mode\": \"adDetails\",\r\n  \"adIds\": [\"1611810664\", \"https://www.linkedin.com/ad-library/detail/1658527466\"]\r\n}\r\n```\r\n\r\n### Example — count only\r\n\r\n```json\r\n{\r\n  \"mode\": \"count\",\r\n  \"searchTerms\": [\"AI\"],\r\n  \"countries\": [\"US\"],\r\n  \"dateOption\": \"last-30-days\"\r\n}\r\n```\r\n\r\n## Output\r\n\r\nEach ad is one dataset row with `recordType: \"ad\"`. Count mode emits `recordType: \"count\"` rows. Empty values are removed at every depth — there are no `null`, empty-string, empty-array, or sentinel rows.\r\n\r\n### Ad fields\r\n\r\n| Field | Description |\r\n| --- | --- |\r\n| `ad_id` | LinkedIn ad / creative ID. |\r\n| `ad_url` | Public Ad Library detail URL. |\r\n| `recordType` | `ad`. |\r\n| `sourceUrl` | The search URL or detail URL that produced the row. |\r\n| `scrapedAt` / `scraped_at` | ISO 8601 UTC scrape timestamp (`scraped_at` is the legacy alias). |\r\n| `advertiser_name`, `advertiser_id`, `advertiser_url`, `advertiser_logo`, `advertiser_tagline` | Advertiser identity. `advertiser_id` is a numeric company ID when available, otherwise a member/showcase slug. |\r\n| `paid_for_by` | Paying legal entity from the detail page. |\r\n| `ad_format`, `creative_type`, `format_label` | Normalized format (`image`, `video`, `carousel`, `document`, `message`, `spotlight`, `job`, `event`, `article`, `follow_company`, `dynamic`, `text`) plus the raw creative type and LinkedIn's label. |\r\n| `headline` | Ad headline when present. |\r\n| `body_text` | Copy preview from the search card (or the full preview when scraping a detail URL directly). |\r\n| `body_text_full` | Full detail-page copy (up to roughly 2,700 characters). |\r\n| `cta_text` | CTA button text (`Learn more`, `Register`, ...). |\r\n| `landing_url`, `landing_url_raw`, `landing_domain`, `is_shortlink` | Cleaned landing URL (only the `trk` parameter is removed), original URL, hostname, and short-link flag. |\r\n| `media` | List of `{type, url, expiresAt}` entries (`image`, `poster`, `video`). |\r\n| `media_urls`, `image_urls`, `video_urls`, `video_poster_url` | Flat media lists for compatibility and convenience. |\r\n| `start_date`, `end_date`, `duration_days`, `is_active` | Run dates and duration from the EU transparency block. `is_active` is only present when an end date exists. |\r\n| `total_impressions`, `impressions_min`, `impressions_max` | Impression range label and parsed bounds. |\r\n| `impressions_by_country` | `{country, shareRaw, sharePct, isUpperBound?, isLowerBound?, estimatedMin?, estimatedMax?}` rows. |\r\n| `targeting_language`, `targeting_location_included`, `targeting_location_excluded`, `targeting_parameters` | EU targeting data. Parameters are `{category, targeted, excluded}` rows. |\r\n| `has_dsa_data` | Always a boolean. `false` means LinkedIn did not publish the EU transparency block for that ad. |\r\n| `country`, `top_country` | The single delivery-country filter when one is set; the largest impression-share country from the DSA block. |\r\n| `variants_count` | Number of creative variants on the detail page. |\r\n\r\n### Count fields\r\n\r\n| Field | Description |\r\n| --- | --- |\r\n| `recordType` | `count`. |\r\n| `sourceUrl` | The search URL used. |\r\n| `scrapedAt` / `scraped_at` | ISO timestamp. |\r\n| `query`, `queryType`, `queryValue` | The search label, e.g. `keyword`, `advertiser`, `payer`, `companyIds`, `filters`. |\r\n| `totalCount` | LinkedIn's reported number of matching ads. |\r\n\r\n## Pagination, dedupe, and limits\r\n\r\n- The Ad Library returns **24 ads per page** and exposes a pagination token.\r\n- The actor follows up to **200 pages (4,800 ads) per search**, then stops. This is the practical ceiling the Ad Library accepts.\r\n- Results are deduplicated by `ad_id` across pages and searches.\r\n- `maxItems` is a global cap across all searches (1–4,800). It trims the final page exactly.\r\n- Broad searches can match hundreds of thousands of ads. Slice them by country, date window, keyword, or exact company IDs to reach more than 4,800 rows.\r\n- `maxItems` limits rows, not requests: with `includeDetails: true`, one detail request is made per collected ad (up to the cap).\r\n\r\n## Reliability and errors\r\n\r\n- The actor uses `curl_cffi` with a Chrome 131 TLS fingerprint and a **fresh Apify Proxy AUTO session/IP for every request** (sticky sessions fail when they land on a blocked IP). Each request is retried up to five times with backoff.\r\n- If AUTO stays blocked, the actor tries a headless browser on AUTO, then the Apify UNBLOCKER group for that request. Proxy setup is automatic; there is no proxy input.\r\n- Partial runs are reported honestly in the status message. If some searches are blocked and others return data, the dataset keeps the good rows and the status says how many queries were blocked.\r\n- If every request is blocked, or a search that should return data comes back empty, the run **fails with a clear message**. It never pushes a fake \"blocked\" row.\r\n- Detail-page failures (404/410 or a transient block) keep the card record and log the failure.\r\n- A legitimate `0 results` search also fails the run with an explicit \"0 results\" message rather than silently succeeding with an empty dataset.\r\n- A run summary (pages, details, query statuses) is saved to the key-value store as `run_summary`.\r\n\r\n## FAQ\r\n\r\n**Do I need a LinkedIn account or cookies?**\r\nNo. The Ad Library is public guest content. The actor makes the same anonymous requests the public site does.\r\n\r\n**Do I need to configure a proxy?**\r\nNo. The actor selects and rotates its proxy automatically.\r\n\r\n**Why do some ads lack impressions, dates, or targeting?**\r\nLinkedIn only publishes that transparency block for ads served in the EU. Non-EU ads have no run dates, impression range, country shares, or targeting data. The `has_dsa_data` flag tells you which is which. This is a source limitation, not a scraper bug.\r\n\r\n**Why are media URLs signed?**\r\nLinkedIn CDN URLs carry an `e=` expiry parameter. The actor exposes the URL and its `expiresAt` date in `media[].expiresAt`. Download or archive media before it expires if you need a permanent copy.\r\n\r\n**What is the difference between `advertisers` and `companyIds`?**\r\n`advertisers` is a fuzzy name search and can include partners or resellers. `companyIds` is exact and is the best way to collect only a specific company's ads.\r\n\r\n**Why is `body_text` shorter than `body_text_full`?**\r\nThe search card shows a truncated preview. `body_text_full` comes from the detail page and is only present when `includeDetails` is on (or when the mode is `adDetails`).\r\n\r\n**How do I get more than 4,800 ads?**\r\nSplit the request by country, date range, keyword, or company ID and run each slice separately. Deduplicate downstream by `ad_id` if slices overlap.\r\n\r\n**Can I see spend, budget, CTR, or conversions?**\r\nNo. LinkedIn does not publish those values in the Ad Library. Impressions are ranges, not exact counts.\r\n\r\n**Is this affiliated with LinkedIn?**\r\nNo. This is an independent third-party actor that reads LinkedIn's public Ad Library. It is not affiliated with or endorsed by LinkedIn Corporation.\r\n\r\n## Limitations\r\n\r\n- Only public Ad Library ads are available; Campaign Manager data is not accessible.\r\n- EU transparency data (dates, impressions, country shares, targeting) is published only for EU-served ads.\r\n- LinkedIn reports impression ranges rather than exact impressions.\r\n- Each search is capped at 4,800 ads (200 pages × 24).\r\n- Media URLs are signed and expire; `expiresAt` is provided for archival planning.\r\n- Per-ad delivery country is not published. `country` reflects a single-country search filter; `top_country` is the largest DSA share.\r\n- Carousel/document slide text and non-EU active status are not published by the source.\r\n- LinkedIn may rate-limit aggressive runs; the actor retries and reports partial results rather than fabricating rows.\r\n",
    "actorDefinition": {
      "actorSpecification": 1,
      "name": "linkedin-ad-library-keyword-and-advertiser-scraper",
      "title": "LinkedIn Ad Library Keyword & Advertiser Scraper",
      "description": "Search the public LinkedIn Ad Library by keyword, advertiser, payer, exact company ID, country, date, or targeting facet. Collect paginated ads with full copy, CTA, landing, video, payer, and EU transparency data.",
      "version": "2.0",
      "buildTag": "latest",
      "meta": {
        "templateId": "python-empty"
      },
      "input": {
        "title": "LinkedIn Ad Library Scraper Input",
        "description": "Search the public LinkedIn Ad Library, scrape specific ads, or count matches. Every keyword, advertiser, payer, and company-ID group becomes its own search; country, date, sort, impression, and targeting filters apply to all searches.",
        "type": "object",
        "schemaVersion": 1,
        "properties": {
          "mode": {
            "title": "Mode",
            "type": "string",
            "description": "What to collect: search the library, open specific ads, process pasted URLs, or count matches only.",
            "editor": "select",
            "default": "search",
            "prefill": "search",
            "enum": [
              "search",
              "adDetails",
              "directUrls",
              "count"
            ],
            "enumTitles": [
              "Search the Ad Library",
              "Specific ad IDs / detail URLs",
              "Pasted Ad Library / company URLs",
              "Count matches only"
            ]
          },
          "searchTerms": {
            "title": "Keywords",
            "type": "array",
            "description": "One or more keyword searches, e.g. 'AI' or 'cloud computing'. Each keyword is an independent search (union), not a combination.",
            "editor": "stringList",
            "items": {
              "type": "string"
            },
            "default": [],
            "example": [
              "AI",
              "cloud computing"
            ]
          },
          "advertisers": {
            "title": "Advertisers",
            "type": "array",
            "description": "Advertiser names (fuzzy accountOwner search) or LinkedIn company URLs. Each name is an independent search. Use companyIds for exact matching.",
            "editor": "stringList",
            "items": {
              "type": "string"
            },
            "default": [],
            "example": [
              "Microsoft",
              "Anthropic"
            ]
          },
          "companyIds": {
            "title": "LinkedIn Company IDs",
            "type": "array",
            "description": "Exact numeric LinkedIn company IDs (for example, Microsoft is 1035). Multiple IDs are OR-ed in one exact search. Company URLs are accepted too.",
            "editor": "stringList",
            "items": {
              "type": "string"
            },
            "default": [],
            "prefill": [
              "1035"
            ],
            "example": [
              "1035",
              "3608"
            ]
          },
          "companyUrls": {
            "title": "Company URLs",
            "type": "array",
            "description": "LinkedIn company page URLs. The actor resolves each public page to its numeric organization ID and searches it exactly.",
            "editor": "stringList",
            "items": {
              "type": "string"
            },
            "default": [],
            "example": [
              "https://www.linkedin.com/company/microsoft"
            ]
          },
          "payer": {
            "title": "Paid for by (payer)",
            "type": "array",
            "description": "Search ads by the legal entity that paid for them, e.g. 'Microsoft Corporation'. Each payer is an independent search.",
            "editor": "stringList",
            "items": {
              "type": "string"
            },
            "default": [],
            "example": [
              "Microsoft Corporation"
            ]
          },
          "advertiserMatch": {
            "title": "Advertiser Name Match",
            "type": "string",
            "description": "Client-side precision for advertiser-name searches. Exact company IDs are never filtered. 'Starts with' removes partner-noise results while keeping names such as 'Microsoft in Business'.",
            "editor": "select",
            "default": "startsWith",
            "enum": [
              "any",
              "startsWith",
              "exact"
            ],
            "enumTitles": [
              "Any match",
              "Starts with",
              "Exact name"
            ]
          },
          "countries": {
            "title": "Countries",
            "type": "array",
            "description": "ISO-3166 alpha-2 delivery country codes (US, GB, DE, ...) or ALL. Multiple codes are sent in one comma-separated filter.",
            "editor": "stringList",
            "items": {
              "type": "string"
            },
            "default": [],
            "example": [
              "US",
              "DE"
            ]
          },
          "dateOption": {
            "title": "Date Range",
            "type": "string",
            "description": "LinkedIn's date window. Use custom-date-range with startDate/endDate for an exact period (maximum 12 months back).",
            "editor": "select",
            "default": "last-30-days",
            "prefill": "last-30-days",
            "enum": [
              "any-time",
              "last-30-days",
              "current-month",
              "current-year",
              "last-year",
              "custom-date-range"
            ],
            "enumTitles": [
              "Any time",
              "Last 30 days",
              "Current month",
              "Current year",
              "Last year",
              "Custom date range"
            ]
          },
          "startDate": {
            "title": "Start Date",
            "type": "string",
            "description": "Start of a custom range (YYYY-MM-DD). Required when dateOption is custom-date-range.",
            "editor": "textfield",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
          },
          "endDate": {
            "title": "End Date",
            "type": "string",
            "description": "End of a custom range (YYYY-MM-DD). Required when dateOption is custom-date-range.",
            "editor": "textfield",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
          },
          "sortOrder": {
            "title": "Sort Order",
            "type": "string",
            "description": "Newest first or oldest first.",
            "editor": "select",
            "default": "newest",
            "enum": [
              "newest",
              "oldest"
            ],
            "enumTitles": [
              "Newest first",
              "Oldest first"
            ]
          },
          "impressionsMinValue": {
            "title": "Minimum Impressions Value",
            "type": "integer",
            "description": "Lower bound of the impression range (EU transparency data only). LinkedIn requires both a minimum and a maximum value.",
            "minimum": 0,
            "maximum": 1000000000,
            "editor": "number"
          },
          "impressionsMinUnit": {
            "title": "Minimum Impressions Unit",
            "type": "string",
            "description": "Unit for the minimum impression value.",
            "editor": "select",
            "default": "none",
            "enum": [
              "none",
              "thousand",
              "million"
            ],
            "enumTitles": [
              "Units",
              "Thousands",
              "Millions"
            ]
          },
          "impressionsMaxValue": {
            "title": "Maximum Impressions Value",
            "type": "integer",
            "description": "Upper bound of the impression range (EU transparency data only). Required together with the minimum value.",
            "minimum": 0,
            "maximum": 1000000000,
            "editor": "number"
          },
          "impressionsMaxUnit": {
            "title": "Maximum Impressions Unit",
            "type": "string",
            "description": "Unit for the maximum impression value.",
            "editor": "select",
            "default": "none",
            "enum": [
              "none",
              "thousand",
              "million"
            ],
            "enumTitles": [
              "Units",
              "Thousands",
              "Millions"
            ]
          },
          "targetingIncluded": {
            "title": "Included Targeting Facets",
            "type": "array",
            "description": "Filters ads that target any of these categories (EU transparency data only). Values: LANGUAGE, LOCATION, AUDIENCE, DEMOGRAPHIC, COMPANY, EDUCATION, JOB, INTERESTS_AND_TRAITS.",
            "editor": "stringList",
            "items": {
              "type": "string"
            },
            "default": [],
            "example": [
              "LANGUAGE",
              "JOB"
            ]
          },
          "targetingExcluded": {
            "title": "Excluded Targeting Facets",
            "type": "array",
            "description": "Filters ads that exclude any of these categories (EU transparency data only). Values: LANGUAGE, LOCATION, AUDIENCE, DEMOGRAPHIC, COMPANY, EDUCATION, JOB, INTERESTS_AND_TRAITS.",
            "editor": "stringList",
            "items": {
              "type": "string"
            },
            "default": [],
            "example": [
              "COMPANY"
            ]
          },
          "includeDetails": {
            "title": "Include Detail Pages",
            "type": "boolean",
            "description": "Open each ad's detail page for full copy, CTA, landing URL, video, payer, and EU transparency data. Adds one request per ad.",
            "default": true,
            "prefill": true,
            "editor": "checkbox"
          },
          "decodeShortLinks": {
            "title": "Decode Short Links",
            "type": "boolean",
            "description": "Resolve lnkd.in and similar short links to their final landing URL. Adds one request per short link.",
            "default": false,
            "editor": "checkbox"
          },
          "adIds": {
            "title": "Ad IDs or Detail URLs",
            "type": "array",
            "description": "Numeric ad IDs or linkedin.com/ad-library/detail/... URLs. Used by mode adDetails.",
            "editor": "stringList",
            "items": {
              "type": "string"
            },
            "default": [],
            "example": [
              "1611810664"
            ]
          },
          "directUrls": {
            "title": "Direct URLs",
            "type": "array",
            "description": "Pasted Ad Library search URLs, ad detail URLs, or LinkedIn company page URLs. Search filters are preserved.",
            "editor": "requestListSources",
            "default": [],
            "example": [
              {
                "url": "https://www.linkedin.com/ad-library/search?keyword=AI&countries=US"
              }
            ]
          },
          "maxItems": {
            "title": "Maximum Records",
            "type": "integer",
            "description": "Global cap on ads returned across all searches (1-4800). Each search can return at most 4,800 ads (200 pages of 24).",
            "default": 50,
            "prefill": 3,
            "minimum": 1,
            "maximum": 4800,
            "editor": "number"
          }
        },
        "required": []
      },
      "output": {
        "actorOutputSchemaVersion": 1,
        "title": "LinkedIn Ad Library Output",
        "description": "Dataset of LinkedIn Ad Library ads (recordType='ad') or match-count rows (recordType='count'). Empty fields are omitted at every depth.",
        "properties": {
          "ads": {
            "type": "string",
            "title": "LinkedIn Ad Library records",
            "description": "All scraped ad records and count rows. Use recordType to separate them.",
            "template": "{{links.apiDefaultDatasetUrl}}/items"
          }
        }
      },
      "dockerfile": "../Dockerfile",
      "readme": "# LinkedIn Ad Library Keyword & Advertiser Scraper\r\n\r\nSearch the **public LinkedIn Ad Library** without an account, cookies, or a login. Collect paginated ads by keyword, advertiser name, payer, exact company ID, or a pasted Ad Library URL — then enrich each ad with its full copy, CTA, landing URL, video, paying entity, and the EU transparency block (run dates, impression range, country shares, and targeting).\r\n\r\nThe actor is built for competitor research, creative monitoring, and B2B ad intelligence. It reads the same public pages a logged-out visitor sees, so it works with zero credentials.\r\n\r\n## Modes\r\n\r\n| Mode | What it does | Inputs it uses |\r\n| --- | --- | --- |\r\n| `search` (default) | Builds one search per keyword / advertiser / payer / company-ID group, paginates it, dedupes by ad ID, and optionally opens every detail page. | `searchTerms`, `advertisers`, `companyIds`, `companyUrls`, `payer`, filters |\r\n| `adDetails` | Re-scrapes specific ads from their IDs or detail URLs. | `adIds`, `directUrls` (detail URLs) |\r\n| `directUrls` | Accepts pasted Ad Library search URLs, company URLs, and ad detail URLs. Search filters are preserved. | `directUrls` |\r\n| `count` | Returns the total number of matching ads per search, without pagination. | The same search inputs |\r\n\r\nEvery keyword, advertiser, payer, and company-ID group is an **independent search** (a union). Filters such as country, date, sort, impressions, and targeting apply to all of them.\r\n\r\n## Inputs\r\n\r\n| Input | Type | Default | Description |\r\n| --- | --- | --- | --- |\r\n| `mode` | Select | `search` | `search`, `adDetails`, `directUrls`, or `count`. |\r\n| `searchTerms` | String list | `[]` | Keyword searches. |\r\n| `advertisers` | String list | `[]` | Advertiser names (fuzzy) or LinkedIn company URLs. |\r\n| `companyIds` | String list | `[]` | Exact numeric LinkedIn company IDs; multiple IDs are OR-ed. URLs are accepted. |\r\n| `companyUrls` | String list | `[]` | Company page URLs, resolved to their numeric organization ID. |\r\n| `payer` | String list | `[]` | Legal entity that paid for the ad. |\r\n| `advertiserMatch` | Select | `startsWith` | Client-side precision for advertiser-name searches: `any`, `startsWith`, `exact`. |\r\n| `countries` | String list | `[]` | ISO-3166 alpha-2 codes (`US`, `GB`, `DE`) or `ALL`. Multiple codes are comma-joined. |\r\n| `dateOption` | Select | `last-30-days` | `any-time`, `last-30-days`, `current-month`, `current-year`, `last-year`, `custom-date-range`. |\r\n| `startDate` / `endDate` | String | — | Required for `custom-date-range` (YYYY-MM-DD, within the last 12 months). |\r\n| `sortOrder` | Select | `newest` | `newest` or `oldest`. |\r\n| `impressionsMinValue` / `impressionsMaxValue` | Integer | — | EU impression range. LinkedIn requires both values. |\r\n| `impressionsMinUnit` / `impressionsMaxUnit` | Select | `none` | `none`, `thousand`, or `million`. |\r\n| `targetingIncluded` / `targetingExcluded` | String list | `[]` | EU targeting facets: `LANGUAGE`, `LOCATION`, `AUDIENCE`, `DEMOGRAPHIC`, `COMPANY`, `EDUCATION`, `JOB`, `INTERESTS_AND_TRAITS`. |\r\n| `includeDetails` | Boolean | `true` | Open each ad's detail page for full copy, CTA, landing URL, video, payer, and EU data. |\r\n| `decodeShortLinks` | Boolean | `false` | Resolve `lnkd.in` and similar short links to the final landing URL. |\r\n| `adIds` | String list | `[]` | Ad IDs or detail URLs, for `adDetails`. |\r\n| `directUrls` | URL list | `[]` | Pasted Ad Library search/detail URLs or company URLs. |\r\n| `maxItems` | Integer | `50` | Global cap per run (1–4,800). |\r\n\r\n### Prefill\r\n\r\nThe default prefill is the smallest run with a reliable result: Microsoft's exact company ID, the last 30 days, three ads, and detail enrichment on.\r\n\r\n```json\r\n{\r\n  \"mode\": \"search\",\r\n  \"companyIds\": [\"1035\"],\r\n  \"dateOption\": \"last-30-days\",\r\n  \"includeDetails\": true,\r\n  \"maxItems\": 3\r\n}\r\n```\r\n\r\n### Example — keyword search, card data only\r\n\r\n```json\r\n{\r\n  \"searchTerms\": [\"AI\", \"machine learning\"],\r\n  \"countries\": [\"US\", \"DE\"],\r\n  \"dateOption\": \"last-30-days\",\r\n  \"includeDetails\": false,\r\n  \"maxItems\": 100\r\n}\r\n```\r\n\r\n### Example — exact advertiser with EU transparency\r\n\r\n```json\r\n{\r\n  \"companyIds\": [\"1035\"],\r\n  \"countries\": [\"DE\"],\r\n  \"dateOption\": \"last-year\",\r\n  \"includeDetails\": true,\r\n  \"maxItems\": 200\r\n}\r\n```\r\n\r\n### Example — re-scrape specific ads\r\n\r\n```json\r\n{\r\n  \"mode\": \"adDetails\",\r\n  \"adIds\": [\"1611810664\", \"https://www.linkedin.com/ad-library/detail/1658527466\"]\r\n}\r\n```\r\n\r\n### Example — count only\r\n\r\n```json\r\n{\r\n  \"mode\": \"count\",\r\n  \"searchTerms\": [\"AI\"],\r\n  \"countries\": [\"US\"],\r\n  \"dateOption\": \"last-30-days\"\r\n}\r\n```\r\n\r\n## Output\r\n\r\nEach ad is one dataset row with `recordType: \"ad\"`. Count mode emits `recordType: \"count\"` rows. Empty values are removed at every depth — there are no `null`, empty-string, empty-array, or sentinel rows.\r\n\r\n### Ad fields\r\n\r\n| Field | Description |\r\n| --- | --- |\r\n| `ad_id` | LinkedIn ad / creative ID. |\r\n| `ad_url` | Public Ad Library detail URL. |\r\n| `recordType` | `ad`. |\r\n| `sourceUrl` | The search URL or detail URL that produced the row. |\r\n| `scrapedAt` / `scraped_at` | ISO 8601 UTC scrape timestamp (`scraped_at` is the legacy alias). |\r\n| `advertiser_name`, `advertiser_id`, `advertiser_url`, `advertiser_logo`, `advertiser_tagline` | Advertiser identity. `advertiser_id` is a numeric company ID when available, otherwise a member/showcase slug. |\r\n| `paid_for_by` | Paying legal entity from the detail page. |\r\n| `ad_format`, `creative_type`, `format_label` | Normalized format (`image`, `video`, `carousel`, `document`, `message`, `spotlight`, `job`, `event`, `article`, `follow_company`, `dynamic`, `text`) plus the raw creative type and LinkedIn's label. |\r\n| `headline` | Ad headline when present. |\r\n| `body_text` | Copy preview from the search card (or the full preview when scraping a detail URL directly). |\r\n| `body_text_full` | Full detail-page copy (up to roughly 2,700 characters). |\r\n| `cta_text` | CTA button text (`Learn more`, `Register`, ...). |\r\n| `landing_url`, `landing_url_raw`, `landing_domain`, `is_shortlink` | Cleaned landing URL (only the `trk` parameter is removed), original URL, hostname, and short-link flag. |\r\n| `media` | List of `{type, url, expiresAt}` entries (`image`, `poster`, `video`). |\r\n| `media_urls`, `image_urls`, `video_urls`, `video_poster_url` | Flat media lists for compatibility and convenience. |\r\n| `start_date`, `end_date`, `duration_days`, `is_active` | Run dates and duration from the EU transparency block. `is_active` is only present when an end date exists. |\r\n| `total_impressions`, `impressions_min`, `impressions_max` | Impression range label and parsed bounds. |\r\n| `impressions_by_country` | `{country, shareRaw, sharePct, isUpperBound?, isLowerBound?, estimatedMin?, estimatedMax?}` rows. |\r\n| `targeting_language`, `targeting_location_included`, `targeting_location_excluded`, `targeting_parameters` | EU targeting data. Parameters are `{category, targeted, excluded}` rows. |\r\n| `has_dsa_data` | Always a boolean. `false` means LinkedIn did not publish the EU transparency block for that ad. |\r\n| `country`, `top_country` | The single delivery-country filter when one is set; the largest impression-share country from the DSA block. |\r\n| `variants_count` | Number of creative variants on the detail page. |\r\n\r\n### Count fields\r\n\r\n| Field | Description |\r\n| --- | --- |\r\n| `recordType` | `count`. |\r\n| `sourceUrl` | The search URL used. |\r\n| `scrapedAt` / `scraped_at` | ISO timestamp. |\r\n| `query`, `queryType`, `queryValue` | The search label, e.g. `keyword`, `advertiser`, `payer`, `companyIds`, `filters`. |\r\n| `totalCount` | LinkedIn's reported number of matching ads. |\r\n\r\n## Pagination, dedupe, and limits\r\n\r\n- The Ad Library returns **24 ads per page** and exposes a pagination token.\r\n- The actor follows up to **200 pages (4,800 ads) per search**, then stops. This is the practical ceiling the Ad Library accepts.\r\n- Results are deduplicated by `ad_id` across pages and searches.\r\n- `maxItems` is a global cap across all searches (1–4,800). It trims the final page exactly.\r\n- Broad searches can match hundreds of thousands of ads. Slice them by country, date window, keyword, or exact company IDs to reach more than 4,800 rows.\r\n- `maxItems` limits rows, not requests: with `includeDetails: true`, one detail request is made per collected ad (up to the cap).\r\n\r\n## Reliability and errors\r\n\r\n- The actor uses `curl_cffi` with a Chrome 131 TLS fingerprint and a **fresh Apify Proxy AUTO session/IP for every request** (sticky sessions fail when they land on a blocked IP). Each request is retried up to five times with backoff.\r\n- If AUTO stays blocked, the actor tries a headless browser on AUTO, then the Apify UNBLOCKER group for that request. Proxy setup is automatic; there is no proxy input.\r\n- Partial runs are reported honestly in the status message. If some searches are blocked and others return data, the dataset keeps the good rows and the status says how many queries were blocked.\r\n- If every request is blocked, or a search that should return data comes back empty, the run **fails with a clear message**. It never pushes a fake \"blocked\" row.\r\n- Detail-page failures (404/410 or a transient block) keep the card record and log the failure.\r\n- A legitimate `0 results` search also fails the run with an explicit \"0 results\" message rather than silently succeeding with an empty dataset.\r\n- A run summary (pages, details, query statuses) is saved to the key-value store as `run_summary`.\r\n\r\n## FAQ\r\n\r\n**Do I need a LinkedIn account or cookies?**\r\nNo. The Ad Library is public guest content. The actor makes the same anonymous requests the public site does.\r\n\r\n**Do I need to configure a proxy?**\r\nNo. The actor selects and rotates its proxy automatically.\r\n\r\n**Why do some ads lack impressions, dates, or targeting?**\r\nLinkedIn only publishes that transparency block for ads served in the EU. Non-EU ads have no run dates, impression range, country shares, or targeting data. The `has_dsa_data` flag tells you which is which. This is a source limitation, not a scraper bug.\r\n\r\n**Why are media URLs signed?**\r\nLinkedIn CDN URLs carry an `e=` expiry parameter. The actor exposes the URL and its `expiresAt` date in `media[].expiresAt`. Download or archive media before it expires if you need a permanent copy.\r\n\r\n**What is the difference between `advertisers` and `companyIds`?**\r\n`advertisers` is a fuzzy name search and can include partners or resellers. `companyIds` is exact and is the best way to collect only a specific company's ads.\r\n\r\n**Why is `body_text` shorter than `body_text_full`?**\r\nThe search card shows a truncated preview. `body_text_full` comes from the detail page and is only present when `includeDetails` is on (or when the mode is `adDetails`).\r\n\r\n**How do I get more than 4,800 ads?**\r\nSplit the request by country, date range, keyword, or company ID and run each slice separately. Deduplicate downstream by `ad_id` if slices overlap.\r\n\r\n**Can I see spend, budget, CTR, or conversions?**\r\nNo. LinkedIn does not publish those values in the Ad Library. Impressions are ranges, not exact counts.\r\n\r\n**Is this affiliated with LinkedIn?**\r\nNo. This is an independent third-party actor that reads LinkedIn's public Ad Library. It is not affiliated with or endorsed by LinkedIn Corporation.\r\n\r\n## Limitations\r\n\r\n- Only public Ad Library ads are available; Campaign Manager data is not accessible.\r\n- EU transparency data (dates, impressions, country shares, targeting) is published only for EU-served ads.\r\n- LinkedIn reports impression ranges rather than exact impressions.\r\n- Each search is capped at 4,800 ads (200 pages × 24).\r\n- Media URLs are signed and expire; `expiresAt` is provided for archival planning.\r\n- Per-ad delivery country is not published. `country` reflects a single-country search filter; `top_country` is the largest DSA share.\r\n- Carousel/document slide text and non-EU active status are not published by the source.\r\n- LinkedIn may rate-limit aggressive runs; the actor retries and reports partial results rather than fabricating rows.\r\n",
      "categories": [
        "MARKETING",
        "BUSINESS"
      ],
      "storages": {
        "dataset": {
          "actorSpecification": 1,
          "title": "LinkedIn Ad Library",
          "views": {
            "overview": {
              "title": "Overview",
              "transformation": {
                "fields": [
                  "advertiser_name",
                  "ad_format",
                  "headline",
                  "body_text",
                  "cta_text",
                  "start_date",
                  "end_date",
                  "total_impressions",
                  "country",
                  "ad_url"
                ]
              },
              "display": {
                "component": "table",
                "properties": {
                  "advertiser_name": {
                    "label": "Advertiser",
                    "format": "text"
                  },
                  "ad_format": {
                    "label": "Format",
                    "format": "text"
                  },
                  "headline": {
                    "label": "Headline",
                    "format": "text"
                  },
                  "body_text": {
                    "label": "Copy preview",
                    "format": "text"
                  },
                  "cta_text": {
                    "label": "CTA",
                    "format": "text"
                  },
                  "start_date": {
                    "label": "Start",
                    "format": "date"
                  },
                  "end_date": {
                    "label": "End",
                    "format": "date"
                  },
                  "total_impressions": {
                    "label": "Impressions",
                    "format": "text"
                  },
                  "country": {
                    "label": "Country",
                    "format": "text"
                  },
                  "ad_url": {
                    "label": "Ad URL",
                    "format": "link"
                  }
                }
              }
            },
            "creatives": {
              "title": "Creatives",
              "transformation": {
                "fields": [
                  "advertiser_name",
                  "ad_format",
                  "headline",
                  "body_text_full",
                  "image_urls",
                  "video_urls",
                  "video_poster_url",
                  "landing_url",
                  "ad_url"
                ]
              },
              "display": {
                "component": "table",
                "properties": {
                  "advertiser_name": {
                    "label": "Advertiser",
                    "format": "text"
                  },
                  "ad_format": {
                    "label": "Format",
                    "format": "text"
                  },
                  "headline": {
                    "label": "Headline",
                    "format": "text"
                  },
                  "body_text_full": {
                    "label": "Full copy",
                    "format": "text"
                  },
                  "image_urls": {
                    "label": "Images",
                    "format": "text"
                  },
                  "video_urls": {
                    "label": "Videos",
                    "format": "text"
                  },
                  "video_poster_url": {
                    "label": "Poster",
                    "format": "image"
                  },
                  "landing_url": {
                    "label": "Landing",
                    "format": "link"
                  },
                  "ad_url": {
                    "label": "Ad URL",
                    "format": "link"
                  }
                }
              }
            },
            "euTargeting": {
              "title": "EU Transparency",
              "transformation": {
                "fields": [
                  "advertiser_name",
                  "country",
                  "total_impressions",
                  "impressions_by_country",
                  "targeting_language",
                  "targeting_location_included",
                  "targeting_parameters",
                  "ad_url"
                ]
              },
              "display": {
                "component": "table",
                "properties": {
                  "advertiser_name": {
                    "label": "Advertiser",
                    "format": "text"
                  },
                  "country": {
                    "label": "Country",
                    "format": "text"
                  },
                  "total_impressions": {
                    "label": "Impressions",
                    "format": "text"
                  },
                  "impressions_by_country": {
                    "label": "Country shares",
                    "format": "text"
                  },
                  "targeting_language": {
                    "label": "Language",
                    "format": "text"
                  },
                  "targeting_location_included": {
                    "label": "Locations",
                    "format": "text"
                  },
                  "targeting_parameters": {
                    "label": "Targeting parameters",
                    "format": "text"
                  },
                  "ad_url": {
                    "label": "Ad URL",
                    "format": "link"
                  }
                }
              }
            }
          }
        }
      }
    },
    "buildNumber": "2.0.2",
    "imageDigest": "91ba33a23d6c73ae3c2bccc4378d915fd56c95992c77e6646d8fd099ee8eafbf",
    "actVersion": {
      "sourceType": "SOURCE_FILES",
      "buildTag": "latest",
      "versionNumber": "2.0"
    },
    "usage": {
      "ACTOR_COMPUTE_UNITS": 0.05311111111111111
    }
  }
}