LinkedIn Ad Library Keyword & Advertiser Scraper
Pricing
from $0.49 / 1,000 results
LinkedIn Ad Library Keyword & Advertiser Scraper
Search the public LinkedIn Ad Library by keyword, advertiser, country, or date range, and get headline, body copy, advertiser info, media URLs, and call-to-action for the ads each search returns.
Pricing
from $0.49 / 1,000 results
Rating
0.0
(0)
Developer
Nimbryxo-studio
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
10 days ago
Last modified
Categories
Security
Limited permissionsShare
Search the public LinkedIn Ad Library without an account, cookies, or a login. Collect paginated ads by keyword, advertiser name, payer, exact company ID, or a pasted Ad Library URL — then enrich each ad with its full copy, CTA, landing URL, video, paying entity, and the EU transparency block (run dates, impression range, country shares, and targeting).
The actor is built for competitor research, creative monitoring, and B2B ad intelligence. It reads the same public pages a logged-out visitor sees, so it works with zero credentials.
Modes
| Mode | What it does | Inputs it uses |
|---|---|---|
search (default) | Builds one search per keyword / advertiser / payer / company-ID group, paginates it, dedupes by ad ID, and optionally opens every detail page. | searchTerms, advertisers, companyIds, companyUrls, payer, filters |
adDetails | Re-scrapes specific ads from their IDs or detail URLs. | adIds, directUrls (detail URLs) |
directUrls | Accepts pasted Ad Library search URLs, company URLs, and ad detail URLs. Search filters are preserved. | directUrls |
count | Returns the total number of matching ads per search, without pagination. | The same search inputs |
Every keyword, advertiser, payer, and company-ID group is an independent search (a union). Filters such as country, date, sort, impressions, and targeting apply to all of them.
Inputs
| Input | Type | Default | Description |
|---|---|---|---|
mode | Select | search | search, adDetails, directUrls, or count. |
searchTerms | String list | [] | Keyword searches. |
advertisers | String list | [] | Advertiser names (fuzzy) or LinkedIn company URLs. |
companyIds | String list | [] | Exact numeric LinkedIn company IDs; multiple IDs are OR-ed. URLs are accepted. |
companyUrls | String list | [] | Company page URLs, resolved to their numeric organization ID. |
payer | String list | [] | Legal entity that paid for the ad. |
advertiserMatch | Select | startsWith | Client-side precision for advertiser-name searches: any, startsWith, exact. |
countries | String list | [] | ISO-3166 alpha-2 codes (US, GB, DE) or ALL. Multiple codes are comma-joined. |
dateOption | Select | last-30-days | any-time, last-30-days, current-month, current-year, last-year, custom-date-range. |
startDate / endDate | String | — | Required for custom-date-range (YYYY-MM-DD, within the last 12 months). |
sortOrder | Select | newest | newest or oldest. |
impressionsMinValue / impressionsMaxValue | Integer | — | EU impression range. LinkedIn requires both values. |
impressionsMinUnit / impressionsMaxUnit | Select | none | none, thousand, or million. |
targetingIncluded / targetingExcluded | String list | [] | EU targeting facets: LANGUAGE, LOCATION, AUDIENCE, DEMOGRAPHIC, COMPANY, EDUCATION, JOB, INTERESTS_AND_TRAITS. |
includeDetails | Boolean | true | Open each ad's detail page for full copy, CTA, landing URL, video, payer, and EU data. |
decodeShortLinks | Boolean | false | Resolve lnkd.in and similar short links to the final landing URL. |
adIds | String list | [] | Ad IDs or detail URLs, for adDetails. |
directUrls | URL list | [] | Pasted Ad Library search/detail URLs or company URLs. |
maxItems | Integer | 50 | Global cap per run (1–4,800). |
Prefill
The default prefill is the smallest run with a reliable result: Microsoft's exact company ID, the last 30 days, three ads, and detail enrichment on.
{"mode": "search","companyIds": ["1035"],"dateOption": "last-30-days","includeDetails": true,"maxItems": 3}
Example — keyword search, card data only
{"searchTerms": ["AI", "machine learning"],"countries": ["US", "DE"],"dateOption": "last-30-days","includeDetails": false,"maxItems": 100}
Example — exact advertiser with EU transparency
{"companyIds": ["1035"],"countries": ["DE"],"dateOption": "last-year","includeDetails": true,"maxItems": 200}
Example — re-scrape specific ads
{"mode": "adDetails","adIds": ["1611810664", "https://www.linkedin.com/ad-library/detail/1658527466"]}
Example — count only
{"mode": "count","searchTerms": ["AI"],"countries": ["US"],"dateOption": "last-30-days"}
Output
Each ad is one dataset row with recordType: "ad". Count mode emits recordType: "count" rows. Empty values are removed at every depth — there are no null, empty-string, empty-array, or sentinel rows.
Ad fields
| Field | Description |
|---|---|
ad_id | LinkedIn ad / creative ID. |
ad_url | Public Ad Library detail URL. |
recordType | ad. |
sourceUrl | The search URL or detail URL that produced the row. |
scrapedAt / scraped_at | ISO 8601 UTC scrape timestamp (scraped_at is the legacy alias). |
advertiser_name, advertiser_id, advertiser_url, advertiser_logo, advertiser_tagline | Advertiser identity. advertiser_id is a numeric company ID when available, otherwise a member/showcase slug. |
paid_for_by | Paying legal entity from the detail page. |
ad_format, creative_type, format_label | Normalized format (image, video, carousel, document, message, spotlight, job, event, article, follow_company, dynamic, text) plus the raw creative type and LinkedIn's label. |
headline | Ad headline when present. |
body_text | Copy preview from the search card (or the full preview when scraping a detail URL directly). |
body_text_full | Full detail-page copy (up to roughly 2,700 characters). |
cta_text | CTA button text (Learn more, Register, ...). |
landing_url, landing_url_raw, landing_domain, is_shortlink | Cleaned landing URL (only the trk parameter is removed), original URL, hostname, and short-link flag. |
media | List of {type, url, expiresAt} entries (image, poster, video). |
media_urls, image_urls, video_urls, video_poster_url | Flat media lists for compatibility and convenience. |
start_date, end_date, duration_days, is_active | Run dates and duration from the EU transparency block. is_active is only present when an end date exists. |
total_impressions, impressions_min, impressions_max | Impression range label and parsed bounds. |
impressions_by_country | {country, shareRaw, sharePct, isUpperBound?, isLowerBound?, estimatedMin?, estimatedMax?} rows. |
targeting_language, targeting_location_included, targeting_location_excluded, targeting_parameters | EU targeting data. Parameters are {category, targeted, excluded} rows. |
has_dsa_data | Always a boolean. false means LinkedIn did not publish the EU transparency block for that ad. |
country, top_country | The single delivery-country filter when one is set; the largest impression-share country from the DSA block. |
variants_count | Number of creative variants on the detail page. |
Count fields
| Field | Description |
|---|---|
recordType | count. |
sourceUrl | The search URL used. |
scrapedAt / scraped_at | ISO timestamp. |
query, queryType, queryValue | The search label, e.g. keyword, advertiser, payer, companyIds, filters. |
totalCount | LinkedIn's reported number of matching ads. |
Pagination, dedupe, and limits
- The Ad Library returns 24 ads per page and exposes a pagination token.
- The actor follows up to 200 pages (4,800 ads) per search, then stops. This is the practical ceiling the Ad Library accepts.
- Results are deduplicated by
ad_idacross pages and searches. maxItemsis a global cap across all searches (1–4,800). It trims the final page exactly.- Broad searches can match hundreds of thousands of ads. Slice them by country, date window, keyword, or exact company IDs to reach more than 4,800 rows.
maxItemslimits rows, not requests: withincludeDetails: true, one detail request is made per collected ad (up to the cap).
Reliability and errors
- The actor uses
curl_cffiwith a Chrome 131 TLS fingerprint and a fresh Apify Proxy AUTO session/IP for every request (sticky sessions fail when they land on a blocked IP). Each request is retried up to five times with backoff. - If AUTO stays blocked, the actor tries a headless browser on AUTO, then the Apify UNBLOCKER group for that request. Proxy setup is automatic; there is no proxy input.
- Partial runs are reported honestly in the status message. If some searches are blocked and others return data, the dataset keeps the good rows and the status says how many queries were blocked.
- If every request is blocked, or a search that should return data comes back empty, the run fails with a clear message. It never pushes a fake "blocked" row.
- Detail-page failures (404/410 or a transient block) keep the card record and log the failure.
- A legitimate
0 resultssearch also fails the run with an explicit "0 results" message rather than silently succeeding with an empty dataset. - A run summary (pages, details, query statuses) is saved to the key-value store as
run_summary.
FAQ
Do I need a LinkedIn account or cookies? No. The Ad Library is public guest content. The actor makes the same anonymous requests the public site does.
Do I need to configure a proxy? No. The actor selects and rotates its proxy automatically.
Why do some ads lack impressions, dates, or targeting?
LinkedIn only publishes that transparency block for ads served in the EU. Non-EU ads have no run dates, impression range, country shares, or targeting data. The has_dsa_data flag tells you which is which. This is a source limitation, not a scraper bug.
Why are media URLs signed?
LinkedIn CDN URLs carry an e= expiry parameter. The actor exposes the URL and its expiresAt date in media[].expiresAt. Download or archive media before it expires if you need a permanent copy.
What is the difference between advertisers and companyIds?
advertisers is a fuzzy name search and can include partners or resellers. companyIds is exact and is the best way to collect only a specific company's ads.
Why is body_text shorter than body_text_full?
The search card shows a truncated preview. body_text_full comes from the detail page and is only present when includeDetails is on (or when the mode is adDetails).
How do I get more than 4,800 ads?
Split the request by country, date range, keyword, or company ID and run each slice separately. Deduplicate downstream by ad_id if slices overlap.
Can I see spend, budget, CTR, or conversions? No. LinkedIn does not publish those values in the Ad Library. Impressions are ranges, not exact counts.
Is this affiliated with LinkedIn? No. This is an independent third-party actor that reads LinkedIn's public Ad Library. It is not affiliated with or endorsed by LinkedIn Corporation.
Limitations
- Only public Ad Library ads are available; Campaign Manager data is not accessible.
- EU transparency data (dates, impressions, country shares, targeting) is published only for EU-served ads.
- LinkedIn reports impression ranges rather than exact impressions.
- Each search is capped at 4,800 ads (200 pages × 24).
- Media URLs are signed and expire;
expiresAtis provided for archival planning. - Per-ad delivery country is not published.
countryreflects a single-country search filter;top_countryis the largest DSA share. - Carousel/document slide text and non-EU active status are not published by the source.
- LinkedIn may rate-limit aggressive runs; the actor retries and reports partial results rather than fabricating rows.