Back to Blog
Engineering

How Long Do Instagram, TikTok and Facebook Media URLs Last? We Read 460,000 Expiry Stamps

October 31, 2026
8 min read
S
By SociaVault Team
InstagramTikTokFacebookmedia URLsCDNdevelopersdata engineering

How Long Do Instagram, TikTok and Facebook Media URLs Last? We Read 460,000 Expiry Stamps

Media links from TikTok, Instagram and Facebook are temporary. TikTok cover images and avatars expire about 24 hours after you fetch them. Instagram images last about 4.4 days. Instagram video files last about 34 hours.

The expiry time is written into each URL, so you don't have to guess. We read it from more than 460,000 unique media links in API responses we pulled on 19 October 2026, and measured how long each kind of link stays valid.

Bar chart of how long media links stay valid after you fetch them, median: TikTok music 6 hours, TikTok avatar 23 hours, TikTok video cover 24 hours, Instagram video file 34 hours, Meta ad video and image 4.4 days, Instagram profile picture 4.4 days, Instagram post image 4.4 days, TikTok photo-post image 15 days.

MediaLinks measuredShortestMedianLongest
TikTok music476 hours6 hours6 hours
TikTok avatar37,97223 hours23 hours48 hours
TikTok video cover105,6125 hours24 hours15 days
Instagram video file5,45732 hours34 hours4.5 days
Meta ad video2,95832 hours4.4 days4.5 days
Meta ad image26,1534.3 days4.4 days30 days
Instagram profile picture16,8544.3 days4.4 days4.5 days
Instagram post image259,0894.3 days4.4 days4.5 days
TikTok photo-post image8,93215 days15 days15 days
TikTok video file136,042No stampNo stampNo stamp
YouTube thumbnail2,877No stampNo stampNo stamp

Times are from the moment the link was fetched. The spread is narrow: 98.7% of TikTok covers expired within 24 hours, and every Instagram post image within 4.5 days.

Two kinds of link carry no expiry stamp. YouTube thumbnails on i.ytimg.com are stable and safe to store. TikTok video file links don't show an expiry time, but we didn't test how long they keep working, so treat them as short-lived too.

These are signed CDN links, a standard way to protect hosted media. The platform adds an expiry time and a signature to each URL, and its servers refuse the link once the time passes. Changing the expiry yourself breaks the signature, so there's no way to extend one.

That's why a profile picture that loaded fine yesterday shows a broken image today, and why Instagram returns "URL signature expired." The link was never meant to be permanent. We cover the fix in detail in why profile picture URLs expire.

How to read the expiry from a URL

Each platform writes the expiry time in a query parameter:

PlatformParameterFormat
Instagram and Facebook (cdninstagram.com, fbcdn.net)oeUnix time in hexadecimal
TikTok (tiktokcdn.com and similar)x-expiresUnix time in seconds

This reads it and tells you how long a link has left. In JavaScript:

function expiresAt(url) {
  const q = new URL(url).searchParams;
  if (q.has("oe")) return parseInt(q.get("oe"), 16); // Instagram and Facebook: hex Unix time
  if (q.has("x-expires")) return Number(q.get("x-expires")); // TikTok: Unix time in seconds
  return null; // no stamp, e.g. YouTube thumbnails
}

function hoursLeft(url) {
  const t = expiresAt(url);
  return t === null
    ? null
    : Math.round(((t - Date.now() / 1000) / 3600) * 10) / 10;
}

// a negative number means the link has already expired
console.log(
  hoursLeft(
    "https://scontent.cdninstagram.com/v/t51/abc.jpg?stp=dst-jpg&oe=6A0D6E08&_nc_cat=1",
  ),
);

And in Python:

import time
from urllib.parse import urlparse, parse_qs

def expires_at(url):
    q = parse_qs(urlparse(url).query)
    if "oe" in q:  # Instagram and Facebook: hex Unix time
        return int(q["oe"][0], 16)
    if "x-expires" in q:  # TikTok: Unix time in seconds
        return int(q["x-expires"][0])
    return None  # no stamp, e.g. YouTube thumbnails

def hours_left(url):
    t = expires_at(url)
    return None if t is None else round((t - time.time()) / 3600, 1)

# a negative number means the link has already expired
print(hours_left("https://scontent.cdninstagram.com/v/t51/abc.jpg?stp=dst-jpg&oe=6A0D6E08&_nc_cat=1"))

Use this before you save or display a link. If there's less than an hour left, fetch a fresh one.

What to do about it

  1. Download media when you collect it. If you need the image or video later, save the file to your own storage the same day. For TikTok, that means within a few hours.
  2. Store the post's ID, not its media URL. The TikTok video ID or the Instagram shortcode never changes. Keep that, and you can always get a fresh link.
  3. Re-fetch to refresh. An expired link can't be fixed, but calling the post or profile endpoint again returns new, valid links. With SociaVault that's 1 credit per post or profile.
  4. Check before you show. If you display images in a dashboard, read the expiry and refresh links that are close to it, rather than waiting for them to break.
  5. Don't put media URLs in long-lived places. Emails, PDFs and spreadsheets outlive the links. Use your own copy of the file instead.

A simple rule of thumb: TikTok links are good for a day, Instagram and Facebook images for four days, and Instagram videos for a day and a half. Plan for less.

Download and keep a copy

This saves a post's images while their links are still valid. Only keep copies of media you have the right to store, such as your own posts or content you've licensed. In JavaScript (Node 18 or later, as an .mjs file):

import { mkdir, writeFile } from "node:fs/promises";

const API = "https://api.sociavault.com/v1/scrape";
const HEADERS = { "x-api-key": process.env.SOCIAVAULT_API_KEY };

// Lists can come back as arrays or as objects with numbered keys
const asList = (x) => (Array.isArray(x) ? x : Object.values(x ?? {}));
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

const params = new URLSearchParams({ handle: "natgeo" });
const res = await fetch(`${API}/instagram/posts?${params}`, {
  headers: HEADERS,
});
if (!res.ok) throw new Error(`HTTP ${res.status}: ${await res.text()}`);
const data = (await res.json()).data ?? {};

await mkdir("media", { recursive: true });
for (const post of asList(data.items)) {
  const [first] = asList(post.image_versions2?.candidates);
  if (!first?.url || !post.code) continue;
  const image = await fetch(first.url);
  if (image.ok)
    await writeFile(
      `media/${post.code}.jpg`,
      Buffer.from(await image.arrayBuffer()),
    );
  await sleep(500);
}

And in Python:

import os
import pathlib
import time

import requests

API = "https://api.sociavault.com/v1/scrape"
HEADERS = {"x-api-key": os.environ["SOCIAVAULT_API_KEY"]}

def as_list(x):
    # Lists can come back as lists or as dicts with numbered keys
    return list(x.values()) if isinstance(x, dict) else (x or [])

r = requests.get(f"{API}/instagram/posts", headers=HEADERS,
                 params={"handle": "natgeo"}, timeout=60)
r.raise_for_status()
data = r.json().get("data") or {}
out = pathlib.Path("media")
out.mkdir(exist_ok=True)
for post in as_list(data.get("items")):
    candidates = as_list((post.get("image_versions2") or {}).get("candidates"))
    if not candidates or not post.get("code"):
        continue
    image = requests.get(candidates[0]["url"], timeout=60)
    if image.ok:
        (out / f"{post['code']}.jpg").write_bytes(image.content)
    time.sleep(0.5)

The file is named after the post's shortcode, so you can always match it back to the post and re-fetch fresh links later.

How we did it

  • Links: every media URL in the responses from our October 2026 research pulls, deduplicated: TikTok creator videos, Instagram posts and hashtag searches, Meta Ad Library results and YouTube channel videos. More than 460,000 links had an expiry stamp and about 157,000 did not.
  • Measure: the expiry time in each URL minus the time we fetched it.
  • Cost: nothing extra. We read links from responses we'd already pulled for other studies.

Limits. We read the expiry stamp, we didn't test when each link actually stopped working, and a CDN can refuse a link earlier. Lifetimes can change whenever a platform changes its CDN settings, so check the stamp in your own data rather than hard-coding these numbers. The table is in the CSV download.

Frequently Asked Questions

How long do Instagram image URLs last?

About 4.4 days from when you fetch them. Every Instagram post image and profile picture in our data expired within 4.5 days. Instagram video files expire sooner, at about 34 hours.

How long do TikTok image URLs last?

About 24 hours for video covers and avatars. Images in TikTok photo posts last longer, about 15 days, and music links about 6 hours.

Why does my Instagram image say "URL signature expired"?

The link was signed with an expiry time, and that time has passed. You can't extend it. Fetch the post or profile again to get a new link.

Can I make an expired media URL work again?

No. The expiry is part of the signature, so editing it breaks the link. Request the content again to get a fresh URL.

Do YouTube thumbnail URLs expire?

No. Thumbnails on i.ytimg.com carry no expiry and are safe to store.


Building something that stores social media images? Sign up for 50 free credits and pull fresh links whenever you need them.

Found this helpful?

Share it with others who might benefit

Ready to Try SociaVault?

Start extracting social media data with our powerful API. No credit card required.