Ad API Guide

Field guide

How long Meta Ad Library creative URLs last, measured on 10,355 links

Every image and video link the Meta Ad Library returns carries its own expiry in the URL. Decoded across three runs and probed live: about 106 hours for ordinary ad media, 32 hours for a minority of videos, 30 days for dynamic-creative images, the same through every third-party route.

By Shirley Lou, ResearchPublished 2026-09-24Facts re-checked 2026-09-24Last material change 2026-09-24

Written for people asking: How long do Meta Ad Library image and video URLs stay valid?Why do Facebook Ad Library media links stop working after a few days?How do I save creatives from the Meta Ad Library without the links dying?

Meta Ad Library creative URLs expire on a clock that is written into the link itself: the `oe=` query parameter is the expiry as a hex Unix timestamp, signed by `oh=`. Across 10,355 CDN links from cohort runs on 15 and 21 September 2026 and a fresh fetch on 24 September, every link carried one. Ordinary ad images and thumbnails were valid for 104 to 108 hours after the fetch (median 106, about four and a half days); most videos the same, but 6 to 16 percent of video links were signed for about 32 hours; dynamic-creative images and page pictures for about 717 hours. The pattern was identical through ScrapeCreators by page, ScrapeCreators by keyword and Apify, so it is Meta's expiry, not the provider's. A live probe of 329 sampled links returned 403 on all 120 past their decoded expiry and 2xx on all 209 before it. The claims circulating that the links die in about 48 hours are right only for the short-signed videos. A monitoring job should download the asset at fetch time, or read `oe=` and re-fetch the ad before it passes; re-fetching returns the same asset under a fresh link.

The expiry is in the URL

A creative link from any Meta Ad Library route looks like this (one from the 21 September run, shortened):

https://scontent-ord5-2.xx.fbcdn.net/v/t39.35426-6/709122912_1492158371769642_5220700374770463278_n.jpg
  ?stp=dst-jpg_s600x600_tt6&_nc_cat=107&...&oh=00_AQLe...&oe=6AB653D5

Three parts matter. The path segment 709122912_1492158371769642_5220700374770463278_n.jpg is the asset id and does not change between fetches. oe=6AB653D5 is the expiry, a Unix timestamp in hex: int("6AB653D5", 16) is 1790333909, which is 2026-09-25T10:58:29Z, and oh= is the signature that makes the expiry tamper-proof. When the timestamp passes, the CDN returns 403 for that link, and only that link; the asset is still served under a freshly signed URL the next time anyone fetches the ad.

Every one of the 10,355 links in the three runs below carried oe=. None had to be probed to know when it would die.

What three runs showed

The check reads the raw Meta receipts from the cohort runs (ten advertisers, first page each, through ScrapeCreators by page name, ScrapeCreators by keyword and Apify’s Meta Ads Scraper), plus a fetch of two of the advertisers on 24 September for a same-day sample, and subtracts each file’s fetch time from each link’s decoded expiry.

Run Files CDN links Distinct assets Ad images and thumbnails Videos Dynamic-creative images and page pictures
2026-09-15 30 5,089 2,267 3,730 links, 104 to 108 h, median 106 1,259 links, median 106 h; 92 at about 32 h 100 links, 716 to 720 h
2026-09-21 30 4,887 2,249 3,635 links, 104 to 108 h, median 106 1,189 links, median 106 h; 70 at about 32 h 63 links, 716 to 720 h
2026-09-24 (two advertisers) 2 379 239 239 links, 104 to 108 h, median 106 108 links, median 106 h; 17 at about 32 h 32 links, 716 to 720 h

The lifetime did not depend on the route. ScrapeCreators by page (1,735 links on 21 September), ScrapeCreators by keyword (1,921) and Apify (1,231) each returned the same three bands, with the same 104-hour floor and 108-hour ceiling for ordinary media. The provider passes Meta’s signed link through; it does not sign its own.

The short band is confined to videos served from Meta’s video-*.xx.fbcdn.net hosts on one path family (/o1/v/t2/f2/m266/); the other video path family (m367) sits in the 106-hour band with the images. The 30-day band is dynamic-creative images on the t0.* path and page profile pictures on t1.*, which are not ad creatives.

The live probe

Decoding says when a link should die; the probe checks that it does. At 2026-09-23T23:37Z the script fetched one byte of a stratified sample of links from each run and band:

Links Past decoded expiry Result
80 from 15 September (images, thumbnails, videos) yes, by 4 days 403 on 80 of 80
40 from 15 September (dynamic-creative, page pictures) no, 30-day band 2xx on 40 of 40
40 from 21 September (32-hour videos) yes, by a day and a half 403 on 40 of 40
80 from 21 September (images, thumbnails, videos, dynamic-creative) no, expire 25 September 2xx on 80 of 80
89 from 24 September no 2xx on 89 of 89

No link was alive past its oe= and none was dead before it. The 1,833 assets that appeared in both cohort runs all came back on 21 September with a new expiry, six days later than the one they carried on 15 September; the 210 shared between 21 and 24 September likewise. Re-fetching the ad is a reliable way to refresh a link.

What this means for a monitoring job

  • Store the asset, keyed by the asset id. The id in the URL path is stable across fetches and across routes (the same ..._n.jpg id came back from ScrapeCreators and Apify). Download at fetch time and the expiry never matters.
  • If you must store links, store oe= next to them. A job can then re-fetch only the ads whose links are inside, say, 12 hours of expiry, instead of re-fetching everything on a 48-hour guess. For ordinary images that is one re-fetch every four days; for the short-signed videos, one a day.
  • Do not plan around 48 hours. The thread that put the 48-hour figure into circulation and a second one saying links die “in a day or two” describe the 32-hour video band, which was 6 to 16 percent of video links in these runs. Ordinary images and most videos last about twice that. A job that re-fetches every two days is safe but does more calls than it needs; a job that assumes four days will lose a share of its videos.
  • Route cost of a refresh. A re-fetch is one page call: ScrapeCreators returned 30 active ads per call on the cohort, so refreshing links for an advertiser’s first page is one call, not one per ad. The Meta platform page has the per-call prices and latencies for each route.

What this run cannot tell you

Three fetch dates over nine days, ten advertisers, mostly US-targeted, first page only. Whether Meta changes the signing window for other regions, for the official Ad Library API, or over a longer horizon is not measured here; the bands were the same on all three dates, which is the extent of the claim. The 30-day band held 195 links in total, so its ceiling is less well established than the 106-hour band’s. The probe used a ranged GET from one network; the 403 on expired links is Meta’s, not a rate limit, since fresh links from the same hosts returned in the same minute.

How this was measured

  • scripts/check-meta-creative-urls.py reads every meta-*.json receipt in the run folders named, decodes oe= on each CDN link, aggregates by run, route and asset type, and probes a sample live. It makes no provider call.
  • The two 24 September receipts were ScrapeCreators company-page calls routed through Treg; the account balance read $19.55 before and after the pair, so they cost under a cent. Both files are published with the check.
  • Output for this run: summary.json (aggregates), urls.csv (one row per link: run, route, advertiser, fetch time, asset type, asset id, decoded expiry, lifetime in hours, CDN host), live.csv (each probed link with its status), and the two 24 September receipts.

Next step

Run the check on your own receipts. Any folder of Meta ad-library responses written by the cohort runner works; the probe is free.

treg auth login
scripts/run-ads-cohort.py evidence/fixtures/ads-cohort-v1.json evidence/ads-runs/$(date +%F)
scripts/check-meta-creative-urls.py --out evidence/ads-url-checks/$(date +%F) --live 40 evidence/ads-runs/$(date +%F)

Download the checker · the cohort · the runner. To decode one link by hand: python3 -c 'import datetime,sys; print(datetime.datetime.utcfromtimestamp(int(sys.argv[1],16)))' 6AB653D5.

Questions this page answers

How long do Meta Ad Library image and video URLs stay valid?

About 106 hours from the fetch for ordinary ad images, thumbnails and most videos, on 10,355 links across three runs in September 2026; about 32 hours for a minority of video links and about 717 hours for dynamic-creative images and page pictures. The exact expiry is in each URL's `oe=` parameter, so you do not have to guess.

Why do Facebook Ad Library media links stop working after a few days?

The links are signed CDN URLs with an expiry timestamp (`oe=`) and a signature (`oh=`). After the timestamp the CDN answers 403 regardless of who requests it: in a live probe on 23 September 2026, 120 of 120 links past their expiry returned 403 and 209 of 209 before it returned the asset.

How do I save creatives from the Meta Ad Library without the links dying?

Download the asset when you fetch the ad and store it under the asset id from the URL path, which is stable across fetches. If you only store links, decode `oe=` and re-fetch the ad before it passes: all 1,833 assets seen in both cohort runs came back with a new expiry at the second fetch.

Relationship: the people who run this site also work on Treg, one of the routes compared on this page. Every Treg figure here is a call we paid for, with the raw response downloadable, and the same fixture is run against the alternatives where their terms allow.


Spotted an error or a changed price? Email corrections@adapiguide.com with the page URL and a source. Corrections are logged on the corrections page.