# LinkedIn Ad Library Scraper (`datapeak/linkedin-ad-library`) Actor

Scrape the LinkedIn Ad Library with no login. Extract ads, advertiser names, creatives, headlines, CTAs, formats and detail URLs as JSON/CSV. Built for B2B competitor research, media buyers and ad intelligence teams. Filter by advertiser or keyword. Pay per result or run via API.

- **URL**: https://apify.com/datapeak/linkedin-ad-library.md
- **Developed by:** [Gal Gilboa](https://apify.com/datapeak) (community)
- **Categories:** Lead generation, Automation, Social media
- **Stats:** 2 total users, 0 monthly users, 86.2% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## LinkedIn Ad Library Scraper — Competitor Ads, Creatives & Targeting

Extract structured data from the public **LinkedIn Ad Library** (linkedin.com/ad-library): every ad a company is running on LinkedIn — ad copy, headline, format, **creative image/video URLs**, run dates, impressions, country breakdown and targeting. No LinkedIn login, no cookies, public pages only.

Built for **B2B marketers, demand-gen teams, and agencies** doing competitor ad research: see your competitors' LinkedIn ads, which creatives they run, how long each ad has been live, and which countries they target.

### Why this Actor?

- **Bulk company lists** — monitor 1 or 100 competitors in a single run (one query per company). Most LinkedIn ads scrapers only handle one company at a time.
- **Creative URLs extracted** — direct links to the ad's image/video files, ready for a swipe file or creative analysis.
- **Date info** — first/last impression dates per ad, so you can spot long-running (i.e. winning) ads and set up change monitoring on a schedule.
- **Keyword mode** — search all LinkedIn ads by topic (e.g. `crm`) to map a whole category.

### What data does it return?

One dataset item per ad:

- Advertiser name, LinkedIn company URL, logo URL, "Paid by" entity
- Ad copy and headline
- Ad format (`single_image`, `video`, `carousel`, `document`, `text`)
- Creative URLs — image URLs and/or video URL
- Landing page URL and CTA text
- First/last impression dates ("Ran from ... to ...") when LinkedIn shows them
- Total impressions range and **impressions per country**
- Targeting facets shown by LinkedIn (language, locations, company size, ...)
- Ad Library detail URL + which query found the ad

### Sample output

```json
{
  "type": "ad",
  "adId": "9001111",
  "adDetailUrl": "https://www.linkedin.com/ad-library/detail/9001111",
  "advertiserName": "HubSpot",
  "advertiserUrl": "https://www.linkedin.com/company/hubspot",
  "paidBy": "HubSpot, Inc.",
  "headline": "The CRM your whole team will actually use",
  "adCopy": "Stop juggling spreadsheets. HubSpot's free CRM gives your team one place to track every deal, contact, and conversation.",
  "ctaText": "Learn more",
  "adFormat": "single_image",
  "imageUrls": ["https://media.licdn.com/dms/image/v2/sponsored-creative-111.jpg"],
  "videoUrl": null,
  "landingPageUrl": "https://www.hubspot.com/crm?utm_source=linkedin",
  "firstImpressionAt": "Jan 5, 2026",
  "lastImpressionAt": "Jun 30, 2026",
  "totalImpressions": "50k-100k",
  "impressionsByCountry": [
    { "country": "United States", "percentage": "45%" },
    { "country": "United Kingdom", "percentage": "20%" }
  ],
  "targeting": [
    { "facet": "Language", "value": "English" },
    { "facet": "Location", "value": "United States, United Kingdom, Israel" }
  ],
  "targetedCountries": ["United States", "United Kingdom", "Israel"],
  "query": "company \"hubspot\"",
  "scrapedAt": "2026-07-11T12:00:00.000Z"
}
```

Fields the Ad Library doesn't show for a given ad come back as `null` / `[]` — the Actor never fails a run over a missing field.

### How to use it

| Input | What it does |
|---|---|
| `companies` | **Bulk list** of advertisers — company names, LinkedIn company URLs, or numeric LinkedIn company IDs (most reliable; visible as `companyIds` in the Ad Library URL) |
| `keyword` | Free-text Ad Library search across all advertisers |
| `maxAdsPerQuery` | Cap per company/keyword query (default 100) |
| `fetchAdDetails` | Open each ad's detail page for dates, impressions, targeting and full creatives (default on) |
| `proxyConfiguration` | **Use Apify RESIDENTIAL proxy** — LinkedIn blocks most datacenter traffic |

### Use cases

- **Competitor ad monitoring** — schedule a weekly run over your competitor list and diff new/retired ads; long-running ads are the ones that work.
- **Creative swipe file** — pull creative URLs + copy for every ad in your category before briefing your next campaign.
- **B2B messaging research** — compare headlines and hooks across a keyword (e.g. every "crm" ad on LinkedIn).
- **Geo strategy** — see which countries competitors put impressions into and what they target.
- **Agency reporting** — attach a client-vs-competitor LinkedIn ads snapshot to monthly reports via the API.

### Pricing (pay per event)

| Event | Price | Meaning |
|---|---|---|
| `ad-scraped` | $0.003 | One ad record in the dataset |

Example: monitoring 20 competitors × 50 ads each = 1,000 ads = **$3.00** per run.
The Actor respects your maximum cost per run and stops cleanly when the limit is reached.

### Fair use & limitations

- Only public, logged-out Ad Library pages are visited — the same transparency data LinkedIn shows any visitor. No login, no member data, low concurrency.
- LinkedIn shows impressions/targeting only for some ads (mainly EU-served ones); other ads return the creative + copy without those panels.
- LinkedIn actively rate-limits automated traffic. Residential proxy is strongly recommended; blocked responses are retried automatically on fresh sessions.

### Integrations

Standard Apify platform features apply: export to JSON/CSV/Excel, API access, webhooks, and scheduled runs for continuous competitor monitoring.

### Development

```bash
npm install
npm test           # parses the saved fixtures, 40 assertions
apify run          # local run (uses ./storage)
```

# Actor input Schema

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

Advertisers to pull ads for — one search per entry. Each entry can be a company name (<code>HubSpot</code>), a LinkedIn company URL (<code>https://www.linkedin.com/company/hubspot</code>), or a numeric LinkedIn company ID (<code>1035</code> — the most reliable form; you can read it from the <code>companyIds</code> parameter after searching on linkedin.com/ad-library). Leave empty if you use a keyword instead.

## `keyword` (type: `string`):

Free-text Ad Library search, e.g. <code>crm</code> — finds ads from any advertiser whose ad content matches the keyword.

## `maxAdsPerQuery` (type: `integer`):

Maximum number of ads collected per company / keyword query.

## `fetchAdDetails` (type: `boolean`):

If enabled (recommended), the Actor opens each ad's detail page to extract run dates, impressions, country breakdown, targeting and full creative URLs. If disabled, only the lighter search-card data is returned (faster, same price per ad).

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

Proxy to use for the requests. Apify RESIDENTIAL proxy is strongly recommended — LinkedIn blocks most datacenter traffic.

## Actor input object example

```json
{
  "companies": [
    "https://www.linkedin.com/company/hubspot"
  ],
  "maxAdsPerQuery": 100,
  "fetchAdDetails": true,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

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

// Run the Actor and wait for it to finish
const run = await client.actor("datapeak/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": ["https://www.linkedin.com/company/hubspot"],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

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

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call datapeak/linkedin-ad-library --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=datapeak/linkedin-ad-library",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

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