# LinkedIn Ad Library Scraper - Competitor Ads & Targeting (`scrapewise/linkedin-ad-library-scraper`) Actor

Scrape LinkedIn Ad Library ads by advertiser, keyword, payer, country and date: ad copy, advertiser, creative (images, video, carousel, document), CTA, landing page, run dates, impressions and targeting where LinkedIn shows them. Daily only-new mode for competitor alerts. No login.

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

## Pricing

from $1.90 / 1,000 ad delivered 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 Library Scraper: competitor ads, creatives, run dates, impressions and targeting

LinkedIn Ad Library Scraper collects **the ads any company runs on LinkedIn**, straight from the public
[LinkedIn Ad Library](https://www.linkedin.com/ad-library/), without a LinkedIn account or cookies. Search by
advertiser, keyword, payer, country and date, and every ad comes back as one clean row: the full ad copy, the
advertiser and who paid for it, the format, the creative (images, video, carousel cards, document, event), the call to
action and landing page, and, for ads shown in the EU, the run dates, estimated impressions by country and the
targeting the advertiser chose.

It is built for B2B marketers, agencies and founders who watch competitors: see which offers, webinars, reports and
free trials a company is pushing right now, which landing pages it sends LinkedIn traffic to, how long each ad runs and
which countries and languages it targets. Together with Meta and Google ad libraries it gives a full picture of a
competitor's paid social.

### At a glance

| What | Price |
|---|---|
| Ad delivered with full details | **US$ 2.50 per 1,000 ads** (US$ 0.0025 each) |
| Ad delivered as a summary row (`includeDetails` off) | US$ 1.00 per 1,000 ads (US$ 0.001 each) |
| Run start | US$ 0.005 per run |

- 5 competitors with 50 ads each = 250 detailed ads = **US$ 0.63 + US$ 0.005**.
- Error rows, duplicates and ads already delivered in earlier runs (`onlyNew`) are never charged. `maxItems` caps each
  search, and a spending limit set on the run stops it cleanly with everything delivered so far.
- No LinkedIn account, no cookies, no extra tools to pay for.

### Quick start

All recent ads of one company shown in Germany, with full details:

```json
{
  "advertisers": ["Adobe"],
  "countries": ["DE"],
  "maxItems": 50
}
```

Several competitors, only ads that mention a webinar, last 30 days, any country:

```json
{
  "advertisers": ["Canva", "Figma"],
  "searchQueries": ["webinar"],
  "dateRange": "last-30-days",
  "maxItems": 100
}
```

Daily alert of new ads (run it on a schedule):

```json
{
  "advertisers": ["Adobe"],
  "onlyNew": true,
  "maxItems": 0
}
```

You can also paste search links copied from the Ad Library after setting filters there, or single ad links such as
`https://www.linkedin.com/ad-library/detail/1595643974`, in `startUrls`.

### Input

| Field | What it does |
|---|---|
| `advertisers` | Company or advertiser names as LinkedIn shows them, one per line. A name also matches the company's showcase pages (for example Adobe returns Adobe, Adobe for Business, Adobe Acrobat and Adobe Creative Cloud). |
| `searchQueries` | Words to find in the ads. Alone, each keyword searches every advertiser; with `advertisers`, each advertiser is searched with each keyword. |
| `payer` | Only ads paid for by this name (the "Paid for by" line, often an agency or the legal entity). |
| `countries` | 2-letter country codes where the ads were shown (`US`, `DE`, `GB`...). Several codes = any of them. Empty = all countries. |
| `dateRange` | `any`, `last-30-days`, `current-month`, `current-year`, `last-year` or `custom` with `startDate` and `endDate` (YYYY-MM-DD). |
| `startUrls` | Ad Library search links or single ad links. |
| `includeDetails` | On (default): every ad with its full detail. Off: faster and cheaper summary rows from the search results. |
| `maxItems` | Ads per search, newest first (default 50; 0 = every ad the search has). |
| `onlyNew` | Remembers the ads delivered before for the same search and delivers only new ones. |
| `proxyConfiguration` | Apify Proxy by default. |

`accountOwner`, `keyword`, `urls`, `maxResults` and `scrapeDetails` are accepted too, so inputs written for other
LinkedIn ad tools keep working.

### Output

One row per ad (`type: ad`):

| Field | What it is |
|---|---|
| `adId`, `adUrl` | Ad Library id and permanent link of the ad |
| `advertiserName`, `advertiserCompanyId`, `advertiserUrl`, `advertiserLogoUrl` | The company page that runs the ad |
| `paidBy` | The "Paid for by" entity (agency or legal entity) |
| `adFormat`, `creativeType` | Single Image Ad, Video Ad, Carousel Ad, Document Ad, Message Ad, Event Ad, LinkedIn Article Ad... and LinkedIn's own creative code |
| `isThoughtLeaderAd` | The ad promotes a post written by a member on behalf of the company (the company stays the advertiser) |
| `adText` | Full ad copy, line breaks kept |
| `headline`, `subheadline` | Headline under the creative |
| `ctaText`, `ctaButtons` | Call to action button(s), for example Learn more, Register, Sign Up |
| `destinationUrl` | Landing page the ad sends people to |
| `imageUrls` | Creative images (carousel cards, document cover and event image included) |
| `videoUrl`, `videoThumbnailUrl` | Video file in the best resolution offered, and its cover |
| `carouselCards` | Each card of a carousel: `title`, `imageUrl`, `url` |
| `document` | Document ads: `title`, `pageCount`, `coverImageUrl` |
| `event` | Event ads: `name`, `startsAt`, `organizer`, `location` |
| `startDate`, `endDate`, `daysRunning` | When the ad ran (YYYY-MM-DD) and for how many days |
| `totalImpressions`, `impressionsMin`, `impressionsMax` | Estimated impressions as LinkedIn shows them (`1k-5k`) and as numbers |
| `impressionsByCountry` | Share of impressions per country: `country`, `share`, `sharePercent` |
| `targetingLanguages`, `targetingLocations`, `targetingExcludedLocations` | Languages and locations the advertiser targeted or excluded |
| `targeting` | Every targeting group LinkedIn lists, with included and excluded values |
| `targetingParameters` | Which audience, company, demographic, education, job and interest targeting was used (`targeted`, `excluded`) |
| `hasEuTransparencyData` | True when the ad carries run dates, impressions or targeting |
| `variantCount` | Number of versions of the ad |
| `detailsIncluded` | False for summary rows |
| `sourceType`, `sourceQuery`, `scrapedAt` | Which search found the ad and when it was collected |

Run dates, impressions and targeting are published by LinkedIn for ads shown in the European Union. For ads shown
only elsewhere those fields are empty, and `hasEuTransparencyData` is false.

One real row from the first quick start (lists shortened):

```json
{
  "type": "ad",
  "adId": "1600920164",
  "adUrl": "https://www.linkedin.com/ad-library/detail/1600920164",
  "advertiserName": "Adobe for Business",
  "advertiserCompanyId": "3509272",
  "advertiserUrl": "https://www.linkedin.com/company/3509272",
  "isThoughtLeaderAd": false,
  "paidBy": "ADOBE SYSTEMS SOFTWARE IRELAND LIMITED",
  "adFormat": "Single Image Ad",
  "creativeType": "SPONSORED_STATUS_UPDATE",
  "adText": "Von Kostensenkungen über kürzere Zykluszeiten bis hin zu höheren Volumina: KI-Vorreiter holen mehr aus derselben Technologie heraus. Entdeckt die fünf Erfolgsfaktoren, die den Unterschied machen.",
  "headline": "Wie KI-Vorreiter bessere Ergebnisse erzielen.",
  "ctaText": "Mehr erfahren",
  "destinationUrl": "https://business.adobe.com/de/resources/sdk/state-of-ai-readiness.html?sdid=K42KVFY8&mv=social&mv2=paidsoc",
  "imageUrls": ["https://media.licdn.com/dms/image/v2/D4E10AQGP0ZOItAN7Ig/image-shrink_1280/..."],
  "startDate": "2026-10-16",
  "endDate": "2026-10-21",
  "daysRunning": 6,
  "totalImpressions": "1k-5k",
  "impressionsMin": 1000,
  "impressionsMax": 5000,
  "impressionsByCountry": [
    {"country": "Germany", "share": "99%", "sharePercent": 99.0},
    {"country": "France", "share": "< 1%", "sharePercent": null}
  ],
  "targetingLanguages": ["Deutsch"],
  "targetingLocations": ["Deutschland"],
  "targetingParameters": [
    {"parameter": "Audience", "targeted": true, "excluded": true},
    {"parameter": "Company", "targeted": false, "excluded": true},
    {"parameter": "Job", "targeted": true, "excluded": true}
  ],
  "hasEuTransparencyData": true,
  "variantCount": 1,
  "detailsIncluded": true,
  "sourceType": "advertiser",
  "sourceQuery": "Adobe"
}
```

In the same test run (30 ads from the search plus one ad link): 9 single image ads, 8 carousels, 8 message ads,
4 videos and 2 article ads, all with advertiser, payer and full copy, and 30 of the 31 with run dates, impressions and
targeting.

### Errors you may see

Every error is a row with `errorCode` and is never charged:

| errorCode | Meaning |
|---|---|
| `INVALID_INPUT` | A field has a wrong value (country code, date, number) |
| `INVALID_URL` | Not a LinkedIn Ad Library search or ad link |
| `NO_RESULTS` | The Ad Library has no ad for this search and filters; check the advertiser name as LinkedIn shows it |
| `NOT_FOUND` | The ad link does not exist or was removed |
| `PERSONAL_PROFILE_AD` | The ad runs from a personal profile, not from a company page (left out, see below) |
| `BLOCKED` | LinkedIn refused every attempt; run it again in a few minutes |
| `NOT_REACHED` | The run timeout arrived before this search |

### Integrations, scheduling and AI agents

- **Schedule** a daily or weekly run in [Apify schedules](https://docs.apify.com/platform/schedules) with
  `onlyNew: true` to get only the ads your competitors launched since the last run.
- **Export** as JSON, CSV, Excel or XML, or read the dataset from the [Apify API](https://docs.apify.com/api/v2).
- **Connect** it to Make, n8n, Zapier, Slack or Google Sheets through
  [Apify integrations](https://docs.apify.com/platform/integrations), for example to post every new competitor ad to
  a channel.
- **AI agents:** call it as a tool through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp)
  in Claude, ChatGPT, Cursor or any MCP client, for example "get the LinkedIn ads Canva ran in Germany this month and
  group them by offer and landing page".

### FAQ

**Do I need a LinkedIn account?** No. The Ad Library is public, and everything comes from it without login or cookies.

**Which companies can I search?** Any company page that ran ads in the last 12 months. Type the name as LinkedIn
shows it; the search also returns the company's showcase pages.

**Why do some ads have no dates, impressions or targeting?** LinkedIn publishes those only for ads shown in the
European Union. Filter by an EU country (`DE`, `FR`, `NL`...) to get them for most ads.

**What about ads from personal profiles?** Ads that a private person runs from their own profile are left out, free.
Thought leader ads (a member's post promoted by a company) are kept with the company as the advertiser, without the
member's name, photo or profile. In message ads the sender's name is replaced by `[sender]`, and email addresses and
phone numbers in any ad copy are removed.

**Is it legal?** The Actor reads the public Ad Library only, which LinkedIn publishes for ad transparency. You are
responsible for how you use the data under the laws that apply to you.

**Something broke or a field is missing?** Open an issue on the Actor page; issues are answered within a day.

### Limitations

- The Ad Library keeps about 12 months of ads, newest first.
- Impressions are ranges as LinkedIn estimates them, not exact counts.
- For ads with several versions, the row shows the first version and `variantCount`.
- Message ads have no landing page link in the Ad Library; their CTA text is still delivered.
- The impressions-range and targeting-type filters of the Ad Library website are not inputs yet; filter the dataset
  by `impressionsMin` or `targetingParameters` instead.

### Changelog

- **21 Oct 2026:** first version: search by advertiser, keyword, payer, country and date, full ad detail with creative,
  CTA, landing page, run dates, impressions by country and targeting, summary mode and only-new mode.

# Actor input Schema

## `advertisers` (type: `array`):

Company or advertiser names as LinkedIn shows them, one per line, for example Adobe or Canva. Each name is one search and also matches the company's showcase pages (Adobe for Business, Adobe Acrobat...). With keywords too, every advertiser is searched with every keyword.

## `searchQueries` (type: `array`):

Words to find in the ads, one per line, for example webinar or free trial. Alone, each keyword searches every advertiser; with advertisers above, it narrows their ads.

## `payer` (type: `string`):

Optional: only ads paid for by this name (the 'Paid for by' line, often an agency or the legal entity).

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

2-letter country codes where the ads were shown, for example US, DE, GB. Several codes = ads shown in any of them. Empty = all countries.

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

When the ads ran. The Ad Library covers about the last 12 months.

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

Custom range start (YYYY-MM-DD). Setting a start or end date switches the range to Custom.

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

Custom range end (YYYY-MM-DD). Empty = today.

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

Optional: search links copied from https://www.linkedin.com/ad-library/ after setting filters there, or single ad links like https://www.linkedin.com/ad-library/detail/1595643974.

## `includeDetails` (type: `boolean`):

On: opens each ad for the full copy, landing page, CTA, video, carousel cards, payer, run dates, impressions and targeting. Off: faster and cheaper summary rows from the search results (advertiser, format, copy preview, headline, creative).

## `maxItems` (type: `integer`):

Cap for each advertiser, keyword or link, newest ads first. 0 = every ad the search has.

## `onlyNew` (type: `boolean`):

On: remembers the ads delivered in earlier runs of the same search (in your account) and delivers only ads not seen before. Skipped ads are free.

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

Apify Proxy by default. Change it only if you know you need to.

## Actor input object example

```json
{
  "advertisers": [
    "Adobe"
  ],
  "countries": [
    "DE"
  ],
  "dateRange": "any",
  "includeDetails": true,
  "maxItems": 50,
  "onlyNew": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `resultsCsv` (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 = {
    "advertisers": [
        "Adobe"
    ],
    "countries": [
        "DE"
    ],
    "maxItems": 50,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapewise/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 = {
    "advertisers": ["Adobe"],
    "countries": ["DE"],
    "maxItems": 50,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("scrapewise/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 '{
  "advertisers": [
    "Adobe"
  ],
  "countries": [
    "DE"
  ],
  "maxItems": 50,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call scrapewise/linkedin-ad-library-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scrapewise/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/qjldfmNypV4jtrvcr/builds/1Q1dfyQxswZPXQJBA/openapi.json
