# LinkedIn Ad Library Scraper + New Ads Monitor (`alucard2392/linkedin-ad-library`) Actor

Get every LinkedIn ad a company runs: ad text, images, video, CTA, landing page, run dates, impressions and targeting. Search by company, keyword or payer, filter by country and date, and monitor competitors for new ads.

- **URL**: https://apify.com/alucard2392/linkedin-ad-library.md
- **Developed by:** [Le Huu Lam](https://apify.com/alucard2392) (community)
- **Categories:** Marketing, Lead generation, Social media
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 1,000 ad scrapeds

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 + New Ads Monitor

Get every ad a company runs on LinkedIn from the public [LinkedIn Ad Library](https://www.linkedin.com/ad-library). Search by **company name or ID, keyword or payer**, filter by **country and date**, and get each ad's **text, headline, images, video, CTA and landing page**. For ads shown in the EU you also get **run dates, impressions (total and by country) and targeting**.

Run it on a schedule with **Only new ads** turned on, and each run returns only the ads your competitors launched since the last one.

No LinkedIn account, login or cookies needed.

### What you can do with it

- **Competitor ad research**: see every image, video, carousel, document, event, message and text ad a rival runs on LinkedIn.
- **B2B ad copy swipe files**: export headlines, ad text, CTAs and landing-page URLs (with their UTM parameters) at scale.
- **New-ad alerts**: schedule a daily or weekly run in monitoring mode and send new ads to Slack, email, Google Sheets or a webhook with Apify integrations.
- **Market mapping**: search a keyword ("cybersecurity", "payroll software") in one or more countries to see who advertises in a category right now.
- **Spend signals**: impressions ranges and country splits show which campaigns get the most delivery (EU-shown ads).

### Input

| Field | What it does |
|---|---|
| **Companies** | One per line: a name (`HubSpot`), a LinkedIn company ID (`68529`) or a company page URL (`linkedin.com/company/68529`). An ID returns only that company's ads; a name also matches other advertisers whose name contains it. |
| **Keywords** | Ads whose text contains the keyword, from any advertiser. |
| **Payers** | The entity in the "Paid for by" line, for example an agency. |
| **Ad Library URLs** | Search URLs copied from linkedin.com/ad-library (their filters are kept), or single ad URLs. |
| **Countries** | 2-letter codes (`US`, `GB`, `DE`…). Empty = all countries. |
| **Date range** | Last 30 days, current month, current year, last year, or a custom **Shown from / until** (LinkedIn allows up to one year back). |
| **Max ads per search** | Stop after this many ads for each line. |
| **Include ad details** | On by default. Opens each ad's page for the full text, landing page, CTA, video, carousel/document/event/message content, and EU dates, impressions and targeting. Turn off for a cheaper list with the preview only (advertiser, format, truncated text, headline, image). |
| **Only new ads** | Skip ads returned by earlier runs with the same monitor name and search. |
| **Proxy** | Apify Proxy (datacenter) is on by default; see Tips. |

Example:

```json
{
  "companies": ["68529", "Salesforce"],
  "keywords": ["CRM"],
  "countries": ["DE", "FR"],
  "dateRange": "last-30-days",
  "maxAdsPerSearch": 200,
  "onlyNewAds": true,
  "monitorName": "crm-competitors"
}
```

### Output

One item per ad. Download as JSON, CSV, Excel or HTML, or read it through the API.

A real item from a test run on 2026-10-19 (`impressionsByCountry` and the long image URLs are as returned):

```json
{
  "adId": "1577949463",
  "adUrl": "https://www.linkedin.com/ad-library/detail/1577949463",
  "advertiserName": "HubSpot",
  "advertiserLogoUrl": "https://media.licdn.com/dms/image/v2/C4D0BAQF8H-SLmMDZlA/company-logo_100_100/company-logo_100_100/0/1646683330132/hubspot_logo?e=1793836800&v=beta&t=i5A6SbaUbI3iqs3fivFQiXXDpnEAHxo_D-QMr_lT99I",
  "format": "Single Image Ad",
  "creativeType": "SPONSORED_STATUS_UPDATE",
  "adText": "Alison Hammond on making people feel seen, and why she never walks in with an agenda. For anyone who sells or presents. GROW Europe, 17 November.",
  "headline": "GROW Europe 2026 · London · Register Today",
  "imageUrls": [
    "https://media.licdn.com/dms/image/v2/D4D10AQHtnmh8KA51mw/image-shrink_1280/B4DaE2T66PKAAc-/0/1791912554430/GROW2026Paidads14png?e=2147483647&v=beta&t=k4_cu1QaiE5PdS-fnb6tczbdk9CijuwN_iHp_PdmQsc"
  ],
  "imageUrl": "https://media.licdn.com/dms/image/v2/D4D10AQHtnmh8KA51mw/image-shrink_1280/B4DaE2T66PKAAc-/0/1791912554430/GROW2026Paidads14png?e=2147483647&v=beta&t=k4_cu1QaiE5PdS-fnb6tczbdk9CijuwN_iHp_PdmQsc",
  "advertiserUrl": "https://www.linkedin.com/company/68529",
  "advertiserCompanyId": "68529",
  "advertiserType": "company",
  "paidBy": "HubSpot, Inc.",
  "variationCount": 1,
  "firstShown": "2026-10-14",
  "lastShown": "2026-10-18",
  "ranText": "Ran from Oct 14, 2026 to Oct 18, 2026",
  "impressions": "< 1k",
  "impressionsMin": 0,
  "impressionsMax": 1000,
  "impressionsByCountry": [
    {
      "country": "United Kingdom",
      "share": "100%"
    }
  ],
  "targeting": {
    "language": {
      "included": [
        "English"
      ]
    },
    "location": {
      "included": [
        "Ireland",
        "United Kingdom"
      ]
    }
  },
  "targetingParameters": [
    {
      "parameter": "Audience",
      "targeted": true,
      "excluded": true
    },
    {
      "parameter": "Demographic",
      "targeted": false,
      "excluded": false
    },
    {
      "parameter": "Company",
      "targeted": false,
      "excluded": true
    },
    {
      "parameter": "Education",
      "targeted": false,
      "excluded": false
    },
    {
      "parameter": "Job",
      "targeted": false,
      "excluded": false
    },
    {
      "parameter": "Member Interests and Traits",
      "targeted": false,
      "excluded": false
    }
  ],
  "cta": "Register",
  "destinationUrl": "https://www.hubspot.com/grow-europe?utm_source=linkedin&utm_medium=paid&utm_campaign=Marketing_Registrations_EN_EMEA_VARIOUS_GROW-Europe-2026_Remarketing_cm1014_ProgramBudget_v5a&utm_id=805100113&hsa_acc=517582366&hsa_cam=805100113&hsa_grp=891725343&hsa_ad=1577949463&hsa_net=linkedin&hsa_ver=3",
  "searchQuery": "68529",
  "scrapedAt": "2026-10-19T05:16:25.195Z"
}
```

Format-specific fields:

- **Video ads**: `videoUrl` (MP4, highest fixed resolution) and `videoPosterUrl`.
- **Carousel ads**: `carouselCards` with each card's title, image and link (when the library shows one).
- **Document ads**: `document` with title, total page count and preview page images in `imageUrls`.
- **Event ads**: `event` with name, time, organizer, location and URL.
- **Message ads**: the message body in `adText` and `messageSender`.
- **Thought-leader / article ads** posted by a person: `advertiserType` is `member`.

#### What LinkedIn shows and what it doesn't

- **Run dates, impressions and targeting are only published for ads shown in the EU** (a Digital Services Act requirement). For other ads these fields are `null` or empty. In a test with `countries: ["DE", "FR"]`, 200 of 200 ads had them; for a US-focused advertiser, about a third did.
- Impressions are **ranges** (`10k-20k`), not exact numbers; `impressionsMin` / `impressionsMax` make them sortable.
- Targeting shows which parameters were used (language, location, and whether audience, company, job, etc. targeting was on), not the exact audience lists.
- Some ads show no landing page in the library (many video ads, for example); `destinationUrl` is then `null`.
- Text in search previews is truncated by LinkedIn; turn on **Include ad details** for full text.

### Pricing

You pay per result, with no subscription and no proxy fees:

| Event | Price |
|---|---|
| Ad | $0.80 per 1,000 ads |
| Ad details (optional, on by default) | $0.60 per 1,000 ads whose detail page was read |

So a full run with details costs **$1.40 per 1,000 ads**. Set a maximum cost per run in the run options and the Actor stops when it reaches it.

### Tips

- **Use the company ID for exact results.** It is the number in the company's LinkedIn URL, or in `advertiserCompanyId` of any result. A name search also returns partners and resellers whose names contain the brand.
- **Speed:** about 100 ads with details per 100 seconds. Requests are paced to stay polite to LinkedIn.
- **Proxy:** LinkedIn rejects a share of requests from cloud servers. The Actor retries them, but with Apify Proxy on (the default) almost none are rejected and runs are faster. In tests: 0 of 105 requests rejected with the proxy, about 40% rejected and retried without it.
- **Monitoring:** results come newest first, so a monitoring run stops after two pages with nothing new.

### Is it legal?

The Actor reads only what LinkedIn publishes in its public Ad Library for ad transparency: ads, the advertisers and the entities that paid for them. It does not log in and collects no data about people who saw the ads. Ads posted by individual members (thought-leader ads) include the name LinkedIn shows as the advertiser. You are responsible for how you use the data. If in doubt, ask your lawyer.

### Feedback

Found a bug or want a field added? Open an issue on the Actor's **Issues** tab. Fixes usually ship within a few days.

# Actor input Schema

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

One per line. A company name ("HubSpot"), a LinkedIn company ID ("68529") or a company page URL (linkedin.com/company/68529). A numeric ID returns only that company's ads; a name also matches other advertisers whose name contains it.

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

One per line. Finds ads whose text contains the keyword, from any advertiser.

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

One per line. The legal entity that paid for the ads (the "Paid for by" line), e.g. an agency.

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

Optional. Paste search URLs from linkedin.com/ad-library (filters in the URL are kept) or single ad URLs (linkedin.com/ad-library/detail/…).

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

2-letter country codes (US, GB, DE, FR…). Leave empty for all countries.

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

Only ads that ran in this period. Ignored when you set Shown from / Shown until.

## `dateFrom` (type: `string`):

Custom range start (YYYY-MM-DD). LinkedIn accepts dates up to one year back.

## `dateTo` (type: `string`):

Custom range end (YYYY-MM-DD).

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

Stop after this many ads for each company, keyword, payer or URL.

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

Open each ad's page to get the full ad text, landing page URL, CTA, video URL, document/event/message content and, for ads shown in the EU, run dates, impressions (total and by country) and targeting. Adds a small extra charge per ad. Turn off for a cheaper, faster list of ads.

## `onlyNewAds` (type: `boolean`):

Remember which ads were already returned and skip them next time. Schedule the Actor daily or weekly to get just the ads your competitors launched since the last run.

## `monitorName` (type: `string`):

Keeps separate memories for different monitors. Use the same name on every scheduled run of one monitor.

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

Apify Proxy (datacenter) is on by default: LinkedIn rejects many requests from shared cloud IPs and the proxy avoids almost all of those retries. Without a proxy the Actor still works, just slower.

## Actor input object example

```json
{
  "companies": [
    "HubSpot"
  ],
  "countries": [],
  "dateRange": "all",
  "maxAdsPerSearch": 100,
  "includeDetails": true,
  "onlyNewAds": false,
  "monitorName": "default",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

One item per ad: advertiser, format, ad text, media URLs, CTA, landing page, run dates, impressions and targeting.

# 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"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("alucard2392/linkedin-ad-library").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"],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("alucard2392/linkedin-ad-library").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"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call alucard2392/linkedin-ad-library --silent --output-dataset

```

## MCP server setup

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

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/Xg7echUlicbmwCfpU/builds/26zlOnfQmeI83E0XD/openapi.json
