LinkedInAnswer

LinkedIn Ad Library API: ads, impressions and targeting

LinkedIn shows run dates, impressions and targeting only for EU ads. Our API exported 48 ads from a Salesforce search with all three in 50 calls.

6 min read

Short answer

  • LinkedIn's Ad Library is a public website, and we found no API for it that you can sign up for.
  • Run dates, impressions and targeting exist only for ads shown in the EU. Search with an EU country such as countries=de and every ad comes back with all three.
  • ToolzerHub returns Ad Library searches as JSON, 24 ads per call, plus one detail call per ad at 1 credit each, so 1,000 ads with details cost 1,042 credits.
On this page

LinkedIn's Ad Library is a public website, and we found no API for it that you can sign up for. ToolzerHub returns its searches and ad pages as JSON, 24 ads a call. Run dates, impressions and targeting come back only for ads shown in the EU, so search an EU country such as de.

What LinkedIn's Ad Library shows

The Ad Library lists ads that ran on LinkedIn after June 1, 2023, and keeps each one for a year after its last impression. You search by advertiser or company name, payer name, keyword, country and date range, and each listing shows the ad preview, format, advertiser and payer.

For ads targeted in the EU, LinkedIn adds the estimated total impressions, the main targeting parameters and the dates the ad ran. The 3 ads we checked from a Salesforce search with no country came back with all three empty, and all 48 ads from the same search limited to Germany had them. For one advertiser's first 24 ads the website is free and also shows impressions by country. The API is for repeating a search across advertisers, countries or weeks and keeping the results in a file.

Search an advertiser's ads with ToolzerHub

We make ToolzerHub. Our LinkedIn API searches the Ad Library with account_owner (the advertiser name), keyword, payer, countries and date filters. Each call is a GET with the x-api-key header and costs 1 credit.

bash
export TOOLZERHUB_API_KEY=your_key
curl -H "x-api-key: $TOOLZERHUB_API_KEY" \
  "https://api.toolzerhub.com/v1/linkedin/ads/search?account_owner=Salesforce&countries=de"

The second of 24 ads that came back, without its thumbnail URL:

json
{
  "ad_id": "1630858566",
  "url": "/ad-library/detail/1630858566",
  "creative_type": "SPONSORED_UPDATE_NATIVE_DOCUMENT",
  "aria_label": "Salesforce, Document Ad, View details",
  "is_video": false
}

The response also has match_count (591 for Salesforce in Germany, 9,122 with no country), is_last_page and a pagination_token. Send the token with the same filters to /v1/linkedin/ads/search/pagination for the next 24.

account_owner matches advertiser names as text. Our Germany search returned ads from 6 advertisers: 21 of 48 from the Salesforce page itself, the rest from pages such as Salesforce Data 360 and Avanza Salesforce Consulting Partner. To keep one page only, filter on aria_label, which starts with the advertiser name, or on advertiser in the detail response.

Get run dates, impressions and targeting for each ad

Search results carry no dates or numbers; one call to /v1/linkedin/ads/detail?ad_id=1630858566 adds them. Trimmed, for the document ad above:

json
{
  "ad_format": "Document Ad",
  "advertiser": "Salesforce",
  "paid_for_by": "Iprospect.com Inc.",
  "run_dates": "Ran from Oct 5, 2026 to Oct 21, 2026",
  "total_impressions": "50k-100k",
  "targeting": {
    "segments": [
      { "parameter": "Language", "mode": "include", "summary": "Targeting includes Deutsch" },
      { "parameter": "Location", "mode": "include", "summary": "Targeting includes Deutschland" }
    ],
    "matrix": [
      { "parameter": "Audience", "targeted": true, "excluded": true },
      { "parameter": "Company", "targeted": true, "excluded": true },
      { "parameter": "Job", "targeted": true, "excluded": false }
    ]
  }
}

Impressions are a band, not a count. The matrix says which kinds of targeting were used (here audience, company and job, not education or demographics), not the exact values.

Export an advertiser's EU ads to CSV

The script runs the search, follows the pagination token, calls the detail route for each ad and writes one row per ad. Pass an EU country code, or the date, impression and targeting columns stay empty.

python
import csv
import os
import sys
import time

import requests

BASE = "https://api.toolzerhub.com/v1/linkedin/ads"
HEADERS = {"x-api-key": os.environ.get("TOOLZERHUB_API_KEY", "")}
FIELDS = ["ad_id", "advertiser", "paid_for_by", "format", "run_dates", "impressions",
          "targeting", "body", "url"]


def get(path, params, tries=3):
    # 429, 500, 503 and dropped connections are retried; failed calls cost no credits.
    for attempt in range(tries):
        last = attempt == tries - 1
        try:
            r = requests.get(f"{BASE}/{path}", headers=HEADERS, params=params, timeout=90)
        except requests.RequestException:
            if last:
                raise
            time.sleep(10 * (attempt + 1))
            continue
        if r.status_code in (429, 500, 503) and not last:
            time.sleep(10 * (attempt + 1))
            continue
        r.raise_for_status()
        return r.json()["data"]


def ads(advertiser, country, pages):
    params = {"account_owner": advertiser, "countries": country}
    data = get("search", params)
    for page in range(pages):
        if not data:
            return
        yield from data["ads"]
        if page == pages - 1 or data.get("is_last_page") or not data.get("pagination_token"):
            return
        data = get("search/pagination", {**params, "pagination_token": data["pagination_token"]})


def targeting(t):
    # Filled only for ads shown in the EU; elsewhere LinkedIn publishes no targeting.
    return " | ".join(s["summary"] for s in (t or {}).get("segments") or [])


def main(advertiser, country, pages="1", out="linkedin_ads.csv"):
    seen = set()
    with open(out, "w", newline="", encoding="utf-8-sig") as f:  # -sig: Excel reads UTF-8
        writer = csv.DictWriter(f, fieldnames=FIELDS)
        writer.writeheader()
        for ad in ads(advertiser, country.lower(), max(1, int(pages))):
            if ad["ad_id"] in seen:
                continue
            seen.add(ad["ad_id"])
            try:
                d = get("detail", {"ad_id": ad["ad_id"]}) or {}
            except requests.RequestException as e:  # keep the row, note the miss
                print(f"no details for {ad['ad_id']}: {e}")
                d = {}
            writer.writerow({
                "ad_id": ad["ad_id"], "advertiser": d.get("advertiser"),
                "paid_for_by": d.get("paid_for_by"), "format": d.get("ad_format"),
                "run_dates": d.get("run_dates"), "impressions": d.get("total_impressions"),
                "targeting": targeting(d.get("targeting")),
                "body": (d.get("body") or "").replace("\n", " ")[:300],
                "url": f"https://www.linkedin.com/ad-library/detail/{ad['ad_id']}",
            })
    print(f"wrote {len(seen)} ads to {out}")


if __name__ == "__main__":
    if len(sys.argv) < 3:
        sys.exit('usage: python linkedin_ads.py "Salesforce" de [pages] [file.csv]')
    if not HEADERS["x-api-key"]:
        sys.exit("set TOOLZERHUB_API_KEY first")
    main(*sys.argv[1:])

python linkedin_ads.py "Salesforce" de 2 made 50 calls and wrote 48 ads in 74 seconds, each with run dates, an impression band and targeting. The 48 rows showed:

  • The payer is often not the advertiser. 16 ads were paid for by Salesforce, Inc., 15 by Iprospect.com Inc. and 6 by Relevize.
  • 28 were single image ads, 6 event ads, 5 document ads, 4 message ads, 3 video ads and 2 carousels.
  • Impression bands ran from under 1k to over 1M; the most common were 1k-5k and 10k-20k, 10 ads each.

What it costs

A search page returns 24 ads and each ad's details cost 1 credit, so 1,000 ads with details is 42 search calls plus 1,000 detail calls, or 1,042 credits. You get 100 free credits a month; $19 buys 10,000 credits that never expire, and plans for higher volume cover more advertisers. Set your key and run the script on your first advertiser.

For LinkedIn's own APIs and what they cost, see LinkedIn API pricing. The same job on other platforms: the Meta Ad Library API and the TikTok Ad Library API.

We are not affiliated with LinkedIn or Microsoft.

Get this data from your own code

The LinkedIn API returns it as JSON with one x-api-key header. 100 free credits monthly.