# LinkedIn Ad Library Scraper (`agnes.developer.queen/linkedin-ad-library-scraper`) Actor

LinkedIn Ad Library Scraper pulls the ads any company runs on LinkedIn, by company, keyword or payer. Returns ad text, headline, image or video, advertiser and payer, plus run dates, impressions by country and targeting for ads shown in the EU. Monitor mode returns only new ads.

- **URL**: https://apify.com/agnes.developer.queen/linkedin-ad-library-scraper.md
- **Developed by:** [Agnes Maina](https://apify.com/agnes.developer.queen) (community)
- **Categories:** Marketing, Social media
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 ads

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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 Library Scraper: competitor ads with copy, pictures, videos, impressions and targeting

LinkedIn Ad Library Scraper is an Apify Actor that pulls the ads a company runs on LinkedIn from the public Ad Library, by company name, keyword or payer, and returns the ad itself, who paid for it, and, where LinkedIn publishes them, its run dates, impressions by country and targeting. No LinkedIn account or cookies.

### Pricing

| Event | Price | You pay when |
|---|---|---|
| Actor start | $0.00005 | once per run |
| Ad | $0.003 | an ad is delivered with its ID, its advertiser and its content (text, headline, picture or video) |

**That is $3 per 1,000 ads. Ads with no text, picture or video are delivered free, with their link.**

### The ad itself, with what LinkedIn knows about it

- Every ad gives the advertiser, the payer, the ad text, the headline, the picture or the video, and where the ad links to.
- Video ads give the MP4 LinkedIn serves, highest quality, and the poster frame.
- Message ads give the sender, the full message and the button text.
- Ads shown in the European Union also give the first and last day they ran, the impressions range, the share of impressions per country, and the targeting: languages, locations, and which of audience, demographic, company, education, job and interests were targeted or excluded. LinkedIn publishes this for EU-shown ads only; a company that advertises in Europe has it on most ads, a US-only advertiser on none.

```json
{
    "advertiserName": "HubSpot",
    "payer": "HubSpot, Inc.",
    "adFormat": "Single Image Ad",
    "text": "$1M to $100M ARR in 18 months. Stuart Shingler, Legora, on how fast-growth companies build trust while they innovate. London, 17 November.",
    "headline": "GROW Europe 2026 · London · Register Today",
    "imageUrl": "https://media.licdn.com/dms/image/v2/D4D10AQGshA0JBhq0cA/image-shrink_1280/...",
    "clickUrl": "https://www.hubspot.com/grow-europe?utm_source=linkedin&utm_medium=paid&...",
    "firstShown": "2026-09-23",
    "lastShown": "2026-09-25",
    "totalImpressions": "5k-10k",
    "impressionsByCountry": [
        { "country": "United Kingdom", "share": 91 },
        { "country": "Ireland", "share": 9 }
    ],
    "targeting": {
        "language": { "includes": ["English"], "excludes": [] },
        "location": { "includes": ["Ireland", "United Kingdom"], "excludes": [] },
        "parameters": [
            { "parameter": "Company", "targeted": true, "excluded": true },
            { "parameter": "Job", "targeted": true, "excluded": false }
        ]
    }
}
```

### How it works

```
company names, keywords, payers or Ad Library URLs
            |
            v
Ad Library search, 24 ads per page, newest first
            |
            v
for each ad, read its detail page: advertiser link, payer, dates,
impressions and targeting where LinkedIn publishes them
            |
            +--> ID, advertiser and content  -->  Ad (charged)
            |
            +--> no content                  -->  delivered free with the link
```

The Ad Library answers browsers only, so pages load in a headless browser on residential proxy, with pictures, fonts and scripts blocked to keep it fast. Turn off `withDetails` to skip the detail pages; the run is then about five times faster and returns what the search results show.

### What data does it extract

| Field | What it is |
|---|---|
| `adId`, `adUrl` | The ad's ID and page in the Ad Library |
| `advertiserName`, `advertiserId`, `advertiserType`, `advertiserUrl` | The advertiser, its LinkedIn company ID or member slug, and its page |
| `payer` | Who paid for the ad, as LinkedIn states it |
| `adFormat`, `creativeType` | Single Image Ad, Video Ad, Message Ad, LinkedIn Article Ad, Job Ad, and LinkedIn's creative type code |
| `text`, `headline`, `description` | The ad copy |
| `imageUrl`, `images` | The ad's picture, and every picture on it |
| `videoUrl`, `videoPosterUrl` | The MP4 and poster frame of a video ad |
| `clickUrl` | Where the ad links to |
| `messageSender`, `callToAction` | Sender and button text of a Message Ad |
| `firstShown`, `lastShown` | When the ad ran, for ads shown in the EU |
| `totalImpressions`, `impressionsLow`, `impressionsHigh` | LinkedIn's impressions range, as text and as numbers |
| `impressionsByCountry` | Each country with its share of impressions in percent |
| `targeting` | Languages, locations and other facets with includes and excludes, and which parameter groups were targeted or excluded |
| `detailsRead` | True when the detail page was read |
| `search` | The search that returned this ad |
| `isNew` | In monitor mode, true when the ad is new since your last run |
| `charged`, `reason` | Whether the row was charged, and why |

### What is NOT returned

- Ad spend or budgets. LinkedIn does not publish them.
- Run dates, impressions or targeting for ads that were not shown in the European Union. LinkedIn publishes these for EU-shown ads only.
- Exact impression counts. LinkedIn gives a range such as 5k-10k.
- The specific companies, job titles or audiences targeted. LinkedIn shows which parameter groups were used, not their values.
- Clicks, engagement or landing page performance.
- Ads LinkedIn has removed from the Ad Library.

### Quick start

1. Open the Actor and enter a competitor's name, for example `HubSpot`.
2. Optionally choose countries and a date range.
3. Run it and open the Ads table, or download JSON, CSV or Excel.

```json
{ "companies": ["HubSpot"], "maxAdsPerSearch": 20 }
```

### Monitor mode

Set `onlyNewSinceLastRun` to true and schedule the run daily or weekly. The first run delivers current ads up to your limit and remembers every ad it saw. Each later run delivers only ads that appeared since, marked `isNew`, and you pay only for those.

### Input

```json
{
    "companies": ["HubSpot", "Salesforce"],
    "keywords": ["webinar"],
    "countries": ["DE", "FR"],
    "dateOption": "last-30-days",
    "maxAdsPerSearch": 100,
    "withDetails": true,
    "onlyNewSinceLastRun": false
}
```

| Field | Type | Default | Description |
|---|---|---|---|
| `companies` | array | | Advertiser names as they appear on LinkedIn |
| `keywords` | array | | Words that appear in the ad. Each keyword is its own search |
| `payers` | array | | The entity that paid for the ads |
| `startUrls` | array | | Search URLs copied from the Ad Library, with filters already set |
| `countries` | array | all | ISO two-letter country codes such as `DE` or `FR`. Only ads shown in those countries. `EU` is not a code and matches nothing; list the member states instead |
| `dateOption` | string | `last-30-days` | `last-30-days`, `current-month`, `current-year`, `last-year` or `custom-date-range` with `startDate` and `endDate` |
| `minImpressions`, `maxImpressions` | integer | | Impressions bounds. LinkedIn applies them to EU-shown ads only, so every other ad is dropped |
| `maxAdsPerSearch` | integer | 100 | Stop after this many ads per company, keyword, payer or URL, up to 5,000 |
| `withDetails` | boolean | true | Read each ad's detail page for the payer, dates, impressions and targeting |
| `onlyNewSinceLastRun` | boolean | false | Monitor mode, deliver only ads new since the last run of the same search |
| `proxyConfiguration` | object | Apify residential | The Ad Library blocks datacenter IPs |

### Output

One full record from a real run.

```json
{
    "adId": "1558773703",
    "adUrl": "https://www.linkedin.com/ad-library/detail/1558773703",
    "advertiserName": "HubSpot",
    "advertiserId": "68529",
    "advertiserType": "company",
    "advertiserUrl": "https://www.linkedin.com/company/68529",
    "payer": "HubSpot, Inc.",
    "adFormat": "Single Image Ad",
    "creativeType": "SPONSORED_STATUS_UPDATE",
    "text": "$1M to $100M ARR in 18 months. Stuart Shingler, Legora, on how fast-growth companies build trust while they innovate. London, 17 November.",
    "headline": "GROW Europe 2026 · London · Register Today",
    "description": null,
    "imageUrl": "https://media.licdn.com/dms/image/v2/D4D10AQGshA0JBhq0cA/image-shrink_1280/B4DaDP9g74HMAc-/0/1790195405027/2png?e=2147483647&v=beta&t=uu-v3Wv8B56hQBJAD5VjRRV3DN-EoRbg-UMe2X3kaSk",
    "images": [
        "https://media.licdn.com/dms/image/v2/D4D10AQGshA0JBhq0cA/image-shrink_1280/B4DaDP9g74HMAc-/0/1790195405027/2png?e=2147483647&v=beta&t=uu-v3Wv8B56hQBJAD5VjRRV3DN-EoRbg-UMe2X3kaSk"
    ],
    "videoUrl": null,
    "videoPosterUrl": null,
    "clickUrl": "https://www.hubspot.com/grow-europe?utm_source=linkedin&utm_medium=paid&utm_campaign=Marketing_Registrations_EN_EMEA_VARIOUS_GROW-Europe-2026_prospecting_cm1013_ProgramBudget_v1a&utm_id=805100113&hsa_acc=517582366&hsa_cam=805100113&hsa_grp=891556833&hsa_ad=1558773703&hsa_net=linkedin&hsa_ver=3",
    "messageSender": null,
    "callToAction": null,
    "firstShown": "2026-09-23",
    "lastShown": "2026-09-25",
    "totalImpressions": "5k-10k",
    "impressionsLow": 5000,
    "impressionsHigh": 10000,
    "impressionsByCountry": [
        { "country": "United Kingdom", "share": 91 },
        { "country": "Ireland", "share": 9 }
    ],
    "targeting": {
        "language": { "includes": ["English"], "excludes": [] },
        "location": { "includes": ["Ireland", "United Kingdom"], "excludes": [] },
        "parameters": [
            { "parameter": "Audience", "targeted": false, "excluded": true },
            { "parameter": "Demographic", "targeted": false, "excluded": false },
            { "parameter": "Company", "targeted": true, "excluded": true },
            { "parameter": "Education", "targeted": false, "excluded": false },
            { "parameter": "Job", "targeted": true, "excluded": false },
            { "parameter": "Member Interests and Traits", "targeted": false, "excluded": false }
        ]
    },
    "detailsRead": true,
    "search": "accountOwner \"HubSpot\"",
    "isNew": null,
    "charged": true,
    "reason": "ad with advertiser and content",
    "scrapedAt": "2026-09-25T12:12:10.512Z"
}
```

### Use from any MCP agent

```
https://mcp.apify.com/?tools=agnes.developer.queen/linkedin-ad-library-scraper
```

Ask the agent what a competitor is advertising on LinkedIn this month. It should read `text`, `headline`, `imageUrl` or `videoUrl`, `clickUrl`, and `totalImpressions` and `targeting` where present.

### Integrations

Call it once per row from Clay, n8n, Make or your own code. This returns the dataset in the same request.

```
POST https://api.apify.com/v2/acts/agnes.developer.queen~linkedin-ad-library-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN
Content-Type: application/json

{ "companies": ["HubSpot"], "maxAdsPerSearch": 20 }
```

It also works with `apify-client`, schedules and webhooks.

### Use cases

- **B2B marketing teams.** Pull every ad three competitors ran in Europe this month, with impressions and the countries they went to.
- **Agencies pitching LinkedIn ads.** Open the pitch with the prospect's own ads, their run dates and what they targeted.
- **Competitive intelligence.** Schedule monitor mode weekly on ten companies and get only the new ads.
- **Copywriters.** Build a swipe file of a category's ads from keyword searches, with the picture or video of each.
- **Sales teams.** Search a keyword in a country to find companies that advertise there, then see what they say.

### FAQ

#### Does it return ad spend?

No. LinkedIn does not publish spend. You get the impressions range for ads shown in the EU.

#### Why do some ads have no dates, impressions or targeting?

LinkedIn publishes those only for ads shown in the European Union. Ads shown elsewhere come with the advertiser, the payer and the ad itself. Set `countries` to EU codes to get ads that carry them.

#### Why was an ad delivered free?

LinkedIn showed no text, picture or video for it. The `reason` field says so, and `adUrl` still opens it.

#### Do I need a LinkedIn account or cookies?

No. The Actor reads the public Ad Library.

#### Can I filter by impressions?

Yes, with `minImpressions` and `maxImpressions`. LinkedIn applies the filter to EU-shown ads, so ads without published impressions are dropped.

#### How often should I run monitor mode?

Weekly is enough for most advertisers. Daily suits companies that launch campaigns often. Each run charges only for new ads.

# Actor input Schema

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

Advertiser names as they appear on LinkedIn, for example HubSpot. Returns the ads that company runs, from the Ad Library's account owner search.

## `keywords` (type: `array`):

Optional. Words that appear in the ad, for example webinar or CRM. Each keyword is its own search.

## `payers` (type: `array`):

Optional. The name of the entity that paid for the ads, when it differs from the advertiser.

## `startUrls` (type: `array`):

Optional. Search URLs copied from linkedin.com/ad-library/search, with any filters already set.

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

ISO two-letter country codes such as US, GB or DE. Only ads shown in those countries are returned. EU is not a code and matches nothing; list the member states instead. Leave empty for all countries.

## `dateOption` (type: `string`):

When the ads ran.

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

For the custom range, YYYY-MM-DD.

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

For the custom range, YYYY-MM-DD.

## `minImpressions` (type: `integer`):

Optional. Only ads with at least this many impressions. LinkedIn publishes impressions only for ads shown in the European Union, so this filter drops every other ad.

## `maxImpressions` (type: `integer`):

Optional. Only ads with at most this many impressions. Same EU limit as above.

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

Stop after this many ads for each company, keyword, payer or URL. Only ads with an ID, an advertiser and content (text, picture or video) are charged.

## `withDetails` (type: `boolean`):

Reads the advertiser link, the payer, run dates, impressions by country and targeting for every ad. Off, the run is about five times faster and returns what the search results show: advertiser, text, headline, picture and link.

## `onlyNewSinceLastRun` (type: `boolean`):

Monitor mode. The first run delivers current ads up to your limit and remembers every ad it saw. Later runs of the same search deliver only ads that appeared since. Schedule it daily or weekly to watch competitors.

## `proxyConfiguration` (type: `object`):

The Ad Library answers browsers on residential IPs. Datacenter IPs are blocked.

## Actor input object example

```json
{
  "companies": [
    "HubSpot"
  ],
  "dateOption": "last-30-days",
  "maxAdsPerSearch": 20,
  "withDetails": true,
  "onlyNewSinceLastRun": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

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

No description

## `summary` (type: `string`):

No description

# 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": [
        "HubSpot"
    ],
    "maxAdsPerSearch": 20,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("agnes.developer.queen/linkedin-ad-library-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": ["HubSpot"],
    "maxAdsPerSearch": 20,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("agnes.developer.queen/linkedin-ad-library-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": [
    "HubSpot"
  ],
  "maxAdsPerSearch": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call agnes.developer.queen/linkedin-ad-library-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,agnes.developer.queen/linkedin-ad-library-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/A88xKG4P7lNb9mevu/builds/HwcVjJXRmeghF4VM6/openapi.json
