# LinkedIn Ad Details Scraper (`blueskyscraper/linkedin-ad-details-scraper`) Actor

Scrape LinkedIn ad details from the Ad Library: impressions range, impressions by country, run dates, who paid, targeted languages, locations and criteria (job, company, audience), CTA, landing page and UTM parameters. By ad URL, company or keyword. No login.

- **URL**: https://apify.com/blueskyscraper/linkedin-ad-details-scraper.md
- **Developed by:** [BlueskyScraper](https://apify.com/blueskyscraper) (community)
- **Categories:** Marketing, Social media, Agents
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.24 / 1,000 ad with details

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

**LinkedIn Ad Details Scraper** opens each ad's page in the public LinkedIn Ad Library and returns what the search list does not show: **total impressions range, impressions by country, run dates, who paid ("Paid for by"), targeted languages and locations, excluded locations, which targeting criteria the advertiser used (company, job, audience, demographic…), the call-to-action button and the landing page with its UTM parameters** — together with the full ad copy and creative. Give it **ad URLs or IDs**, **competitors' company pages**, or a **search**. No LinkedIn login. **$3.2 per 1,000 ads with details, no start fee.**

### What is LinkedIn Ad Details Scraper?

The **LinkedIn ad impressions and targeting** tool. LinkedIn publishes reach and targeting data for ads it reports under the EU Digital Services Act, but only one ad at a time, behind the "About the ad" page. This Actor collects those pages into one table, so you can sort competitors' ads by impressions, see which countries they reach, and which audiences they target — and use it as an unofficial **LinkedIn ad targeting API**.

Every row is one ad with every detail field, so the dataset is ready for a spreadsheet, a BI dashboard or an LLM without joins.

### What data does it extract?

| Field | Example | Meaning |
|---|---|---|
| `impressions`, `impressionsMin`, `impressionsMax` | `50k-100k`, `50000`, `100000` | Total impressions range, also as numbers |
| `impressionsByCountry` | `[{country: "United Kingdom", share: "43%", percent: 43}, …]` | Share of impressions per country |
| `topCountry` | `United Kingdom` | Country with the largest share |
| `ranFrom`, `ranTo`, `runDays` | `2026-09-14`, `2026-10-02`, `19` | When the ad ran |
| `paidBy` | `HubSpot, Inc.` | The "Paid for by" entity |
| `targetingLanguages` | `["English"]` | Targeted languages |
| `targetingLocations`, `targetingExcludedLocations` | `["Dallas, TX", "Germany", "Chicago, IL"…]`, `["India", "New Zealand"]` | Targeted and excluded places |
| `targetedParameters`, `excludedParameters` | `["Company", "Job"]` | Which kinds of targeting were used to include or exclude people |
| `targetingCriteria` | `[{parameter: "Job", targeted: true, excluded: false}, …]` | Every targeting parameter with its flags |
| `ctaText` | `Learn more` | Call-to-action button |
| `landingUrl`, `landingDomain`, `utmParameters` | the landing page, `hubs.la`, `{utm_campaign: …, hsa_cam: …}` | Where the ad sends people, and its campaign tags |
| `advertiserName`, `advertiserUrl`, `advertiserCompanyId` | `HubSpot`, `https://www.linkedin.com/company/68529`, `68529` | Advertiser |
| `format`, `text`, `headline`, `imageUrl`, `videoUrl`, `carouselCards` | `Single Image Ad`, full ad copy… | The creative |
| `variantCount` | `1` | Versions of the creative LinkedIn shows |

**Which ads have impressions and targeting?** Those LinkedIn reports under the EU Digital Services Act — ads that reached people in the EU. In our tests 150 of 150 ads found with a German country filter had an impressions range and 143 had targeting; 10 of 10 HubSpot ads shown in Germany had impressions by country. For ads shown only outside the EU, LinkedIn's page has no impressions or targeting and those fields stay empty. **Impressions by country** appear up to 48 hours after an ad starts — the freshest ads show the total range but no country split yet. Nothing is estimated.

### 💰 How much does it cost?

| Event | Free plan | Starter (Bronze) | Scale (Silver) | Business, Platinum, Diamond |
|---|---|---|---|---|
| **Ad with details** — one ad with impressions, countries, targeting, landing page and full creative | $0.0032 ($3.2 / 1K) | $0.00288 ($2.88 / 1K) | $0.00256 ($2.56 / 1K) | $0.00224 ($2.24 / 1K) |
| Ads whose page could not be read, searches with no ads, error rows, start of a run | free | free | free | free |

On the Apify Free plan the monthly $5 credit buys about **1,562 ads with details**. The most-used LinkedIn ads actor in Apify Store charges $4 per 1,000 ads with details on the Free plan (3 October 2026) — this Actor is 20% below. **Max cost per run** is respected to the cent: ad pages the budget cannot pay for are not even opened.

### How to get LinkedIn ad impressions and targeting

1. Press **Try for free** (an Apify account is free).
2. Paste **Ad URLs or IDs** (`https://www.linkedin.com/ad-library/detail/1560106944`), or competitors' **company pages** (`https://www.linkedin.com/company/hubspot/`), or **search terms**.
3. For companies and searches, set **Countries** — an EU country such as `DE` or `FR` returns ads with every field filled — and **Ads per search**.
4. Press **Start**. The default run (10 HubSpot ads shown in Germany) takes about 20 seconds.
5. Open the **Impressions & targeting** tab, or download Excel, CSV or JSON.

### ⬇️ Input

```json
{
    "adUrls": [
        "https://www.linkedin.com/ad-library/detail/1560106944",
        "1566857653"
    ],
    "companies": ["https://www.linkedin.com/company/hubspot/"],
    "countries": ["DE"],
    "maxAdsPerSearch": 50
}
```

| Field | What it does |
|---|---|
| `adUrls` | Single ads by Ad Library URL or ID |
| `companies` | Company page URL, ID or name — every ad of that company, with details |
| `searchTerms`, `searchType` | Search the Ad Library (keyword, advertiser, payer, company ID) and open every ad found |
| `countries` | Only ads shown in these countries |
| `maxAdsPerSearch` | Ads per company or search line (default 10, max 5,000) |
| `dateRange`, `startDate`, `endDate`, `sortOrder` | When the ads ran, newest or oldest first |
| `onlyNewRowsStore` | Memory name: later runs return only new ads |

### ⬆️ Output

```json
{
    "type": "ad",
    "adId": "1560106944",
    "url": "https://www.linkedin.com/ad-library/detail/1560106944",
    "advertiserName": "HubSpot",
    "advertiserCompanyId": "68529",
    "format": "Single Image Ad",
    "headline": "Sell from anywhere, close everywhere.",
    "detailsScraped": true,
    "paidBy": "HubSpot, Inc.",
    "ranFrom": "2026-09-14",
    "ranTo": "2026-10-02",
    "runDays": 19,
    "impressions": "50k-100k",
    "impressionsMin": 50000,
    "impressionsMax": 100000,
    "topCountry": "United Kingdom",
    "impressionsByCountry": [
        { "country": "United Kingdom", "share": "43%", "percent": 43 },
        { "country": "Ireland", "share": "19%", "percent": 19 },
        { "country": "Germany", "share": "18%", "percent": 18 }
    ],
    "targetingLanguages": ["English"],
    "targetingLocations": ["Dallas, TX", "Germany", "Chicago, IL", "England", "United Kingdom"],
    "targetingExcludedLocations": ["India", "New Zealand", "United Arab Emirates"],
    "targetedParameters": ["Company", "Job"],
    "ctaText": "Learn more"
}
```

An ad whose page LinkedIn does not load (removed ad, wrong ID) comes back as a free row with `type: "error"`; it is never billed.

### 🔁 Get only new LinkedIn ads — schedule it

A one-off export is useful once; a feed of **new** ads is useful every day. Fill **Only new ads — memory name** (for example `competitors-weekly`) and the Actor remembers every ad it delivered under that name. Every later run with the same name writes — and charges — **only ads you have not received before**. Ads delivered earlier are skipped before their page is even opened, so details are not paid twice either.

1. Run once with the memory name to load the current ads.
2. Open the run → **Actions → Schedule** (or [Schedules](https://console.apify.com/schedules)) and pick daily or weekly.
3. Read the new ads from each run's dataset, or connect a webhook, Slack, n8n, Make or Zapier.

Each memory name is separate: one per competitor list or market. To start over, use a new name.

### Use cases

#### Reach benchmarking

Sort a competitor's ads by `impressionsMin` to see which creatives got the most reach, and by `runDays` to see which ones they keep running.

#### Market footprint

`impressionsByCountry` shows where the budget actually lands — useful before entering a European market.

#### Targeting playbooks

`targetedParameters`, `targetingLocations` and `targetingLanguages` reveal whether competitors target job titles, company lists or audiences, and where.

#### Funnel and campaign analysis

`landingUrl` and `utmParameters` show landing pages, campaign names and LinkedIn campaign IDs (`hsa_cam`).

### Integrations

#### Apify API (Python and JavaScript)

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")
run = client.actor("blueskyscraper/linkedin-ad-details-scraper").call(run_input={"companies": ["https://www.linkedin.com/company/hubspot/"], "countries": ["DE"], "maxAdsPerSearch": 50})
for ad in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(ad.get("advertiserName"), ad.get("format"), ad.get("impressions"))
```

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_API_TOKEN>' });
const run = await client.actor('blueskyscraper/linkedin-ad-details-scraper').call({ adUrls: ['https://www.linkedin.com/ad-library/detail/1560106944'] });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

#### No-code: n8n, Make, Zapier, Google Sheets

Use the Apify app in n8n, Make or Zapier: *Run Actor* → *Get dataset items*. For Google Sheets, use the Google Sheets integration on the Actor's Integrations tab, or download the run as Excel or CSV.

#### MCP server for AI agents

Connect `https://mcp.apify.com/?actors=blueskyscraper/linkedin-ad-details-scraper` to Claude, ChatGPT, Cursor or any MCP client, then ask in plain words — for example *"Which of HubSpot's LinkedIn ads in Germany got the most impressions, and how are they targeted?"* The input fields are written so an agent can call the Actor correctly without reading this page.

### 🤖 For AI agents

Actor `blueskyscraper/linkedin-ad-details-scraper`. **Purpose:** LinkedIn ad details — impressions, impressions by country, run dates, payer, targeting, CTA, landing page — one row per ad. **Minimal input:** `{"adUrls": ["https://www.linkedin.com/ad-library/detail/1560106944"]}` or `{"companies": ["https://www.linkedin.com/company/hubspot/"], "countries": ["DE"]}`. Empty impressions/targeting mean LinkedIn does not publish them for that ad (not EU-reached), not zero. Billed per row as `ad-with-details`; error rows are free.

### ❓ FAQ

#### Is it legal to scrape the LinkedIn Ad Library?

The Ad Library is a public transparency tool that LinkedIn publishes for anyone to search without logging in, and this Actor reads only those public pages. It does not log in or touch private profiles. Ads can contain names of people (Thought Leader ads, message senders); if you store or process them, the GDPR and similar laws apply to you. Check LinkedIn's terms and consult a lawyer for your specific use.

#### Does it need a LinkedIn account or cookies?

No. Nothing is logged in, so there is no account to get restricted, and no browser either — runs finish in seconds.

#### Can I use LinkedIn Ad Details Scraper with the Apify API?

Yes. Every run can be started and read over the REST API or the Python and JavaScript clients above, so it works as an unofficial **LinkedIn Ads API** for ad intelligence.

#### Can I use it through an MCP server?

Yes, through the Apify MCP server — see Integrations.

#### Can I integrate it with other apps?

Yes: n8n, Make, Zapier, Google Sheets, Slack, webhooks, and anything that can call an HTTP API.

#### Why are impressions or targeting empty for some ads?

LinkedIn publishes run dates, impressions and targeting only for ads it reports under the EU Digital Services Act — ads that reached people in the EU. For ads shown only outside the EU those fields stay empty. **Impressions by country** appear once LinkedIn publishes them, which can take up to 48 hours after an ad starts; very fresh ads show the total impressions range but no country split yet. The Actor never estimates numbers LinkedIn does not show.

#### What happens when a search finds nothing?

You get one free row with `type: "error"` saying so, with a hint (remove the country filter, widen the dates). A search with no ads is a valid answer, not a failure, and nothing is charged.

#### Is it one row per ad?

Yes. The same ad found by two searches or two companies in one run appears once.

#### Can I get impressions for US-only ads?

No — LinkedIn does not publish impressions or targeting for ads that never reached the EU, and the Actor does not guess them. You still get the advertiser, payer, creative, CTA and landing page for those ads.

#### What do "Company" and "Job" in targetedParameters mean?

They are LinkedIn's targeting categories: the advertiser chose people by company (name, industry, size) and by job (title, function, seniority). LinkedIn does not publish the exact values, only which categories were used.

### Your feedback

Something missing or wrong? Open an issue on the Issues tab — we answer quickly. If the Actor saves you time, a review helps other buyers find it.

### You might also like

| Actor | What it does |
|---|---|
| [LinkedIn Ads Scraper](https://apify.com/blueskyscraper/linkedin-ads-scraper) | Search the LinkedIn Ad Library by keyword, advertiser, payer or company ID |
| [LinkedIn Competitor Ads Scraper](https://apify.com/blueskyscraper/linkedin-competitor-ads-scraper) | Paste a competitor's LinkedIn company page and get every ad it runs |
| [LinkedIn Company Details Scraper](https://apify.com/blueskyscraper/linkedin-company-details-scraper) | Size, industry, website and followers of the advertisers you find |
| [LinkedIn Company Posts Scraper](https://apify.com/blueskyscraper/linkedin-company-posts-scraper) | A company's organic posts next to its paid ads |
| [LinkedIn Company Jobs Scraper](https://apify.com/blueskyscraper/linkedin-company-jobs-scraper) | Who the advertiser is hiring right now |
| [LinkedIn Scraper](https://apify.com/blueskyscraper/linkedin-scraper) | Profiles, companies and posts in one Actor, no login |

**Also known as:** LinkedIn ad impressions, LinkedIn ad targeting scraper, LinkedIn Ad Library details, LinkedIn ads reach by country, LinkedIn ad landing pages, LinkedIn DSA ad data.

# Actor input Schema

## `adUrls` (type: `array`):

Single ads from the LinkedIn Ad Library: <code>https://www.linkedin.com/ad-library/detail/1560106944</code> or just <code>1560106944</code>. Every ad comes back with its details.

## `companies` (type: `array`):

Get details for a company's ads, one company per line: a LinkedIn company page (<code>https://www.linkedin.com/company/hubspot/</code>), a company ID (<code>68529</code>) or a name. Every ad found is opened and returned with impressions, countries and targeting.

## `searchTerms` (type: `array`):

Or search the Ad Library and open every ad found: a keyword from the ad copy (<code>cybersecurity</code>), an advertiser name, a payer name or a company ID, depending on <b>Search by</b>.

## `searchType` (type: `string`):

How to read the search terms. <b>Keyword</b> finds ads whose copy contains the word; <b>Advertiser</b> matches the company or person shown on the ad (partial names match: <code>hubspot</code> also returns HubSpot partners); <b>Payer</b> matches the "Paid for by" entity; <b>Company ID</b> returns exactly one company's ads.

## `countries` (type: `array`):

Keep only ads shown in these countries — two-letter codes: <code>DE</code>, <code>FR</code>, <code>NL</code>, <code>US</code>… LinkedIn publishes impressions and targeting for ads that reached the EU: an EU country here gives detail rows with every field filled. Empty = all countries.

## `maxAdsPerSearch` (type: `integer`):

How many ads to take from each search line, newest first. LinkedIn serves 24 per page; up to 5,000 per search per run.

## `dateRange` (type: `string`):

Keep only ads that ran in this period. For exact dates use Start date / End date below instead.

## `startDate` (type: `string`):

Custom range start, YYYY-MM-DD (for example <code>2026-01-01</code>). Overrides Date range.

## `endDate` (type: `string`):

Custom range end, YYYY-MM-DD (for example <code>2026-03-31</code>). Overrides Date range.

## `sortOrder` (type: `string`):

Newest ads first (LinkedIn's default) or oldest first.

## `onlyNewRowsStore` (type: `string`):

Give this run a name — <code>my-ads-watch</code> — and the Actor remembers every ad it delivered under that name. Every later run with the same name writes and charges <b>only ads you have not received before</b>. Schedule the Actor daily to get a feed of new LinkedIn ads instead of the whole list each time. Leave empty to get everything found, every time.

## `maxConcurrency` (type: `integer`):

How many ad pages to open at once when details are on. 4 is safe; higher is faster but gets more refusals.

## Actor input object example

```json
{
  "companies": [
    "https://www.linkedin.com/company/hubspot/"
  ],
  "searchType": "keyword",
  "countries": [
    "DE"
  ],
  "maxAdsPerSearch": 10,
  "dateRange": "any",
  "sortOrder": "newest",
  "maxConcurrency": 4
}
```

# Actor output Schema

## `ads` (type: `string`):

One row per ad from the LinkedIn Ad Library: advertiser, format, ad copy, headline, image or video, carousel cards, document and event details; with details also who paid, run dates, total impressions, impressions by country, targeting, call to action and landing page. Error rows explain inputs that could not be read.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "companies": [
        "https://www.linkedin.com/company/hubspot/"
    ],
    "countries": [
        "DE"
    ],
    "maxAdsPerSearch": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("blueskyscraper/linkedin-ad-details-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "companies": ["https://www.linkedin.com/company/hubspot/"],
    "countries": ["DE"],
    "maxAdsPerSearch": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("blueskyscraper/linkedin-ad-details-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "companies": [
    "https://www.linkedin.com/company/hubspot/"
  ],
  "countries": [
    "DE"
  ],
  "maxAdsPerSearch": 10
}' |
apify call blueskyscraper/linkedin-ad-details-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,blueskyscraper/linkedin-ad-details-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/pl63g6Sculu9nHyta/builds/nQDph3vReSqASs0OT/openapi.json
