og:image Not Updating After a Change? It's Almost Always Caching
If your og:image was working before and now shows an old version after a change, the tag is very likely fine — a cache is holding onto the previous image. Here's exactly where to look.
August 16, 20268 min read
There's an important distinction between an og:image that has never shown up and one that used to work fine and now shows the wrong, outdated picture after you changed it. The first is usually a markup or reachability problem. The second — og:image not updating — is a different diagnosis almost entirely: some layer between your page and the person viewing the share is holding onto a stale copy, and the fix is finding which layer that is, not debugging your tags again from scratch.
Confirm the live page actually changed first
Before chasing a cache, rule out the simpler possibility: the deploy didn't actually ship the change, or it shipped to a different environment than the one being shared. Load the page's raw HTML source directly — not through a cached CDN edge if you can avoid it, and definitely not through a platform's preview — and confirm the og:image content value in the actual response is the new URL or new file, not the old one. If the source itself still shows the old value, this isn't a caching problem at all; it's a deploy problem, and no amount of forcing a platform to re-scrape will fix it.
Layer one: the platform's own scrape cache
Once you've confirmed the live page is correct, the most likely remaining culprit is the sharing platform's own cached scrape — the same mechanism covered in detail elsewhere, where Facebook, LinkedIn, and others store the result of the first time they crawled a URL and keep reusing it. Facebook's Sharing Debugger and LinkedIn's Post Inspector both let you force a fresh scrape directly. Platforms without a public debugger, including X, Slack, Discord, and iMessage, generally require a cache-busting change to the URL itself (a new or modified query parameter) to guarantee a fresh fetch, since there's no button to force one directly.
Layer two: your own CDN or reverse proxy
This layer gets missed constantly. If your site sits behind a CDN, a reverse proxy, or any edge caching layer, that layer might be serving the platform's crawler a cached HTML response from before your change — meaning the crawler is technically re-scraping, but what it's fetching is itself stale. Check the response headers on the exact request path the crawler hits (cache-control, age, and any custom cache headers your CDN adds) rather than assuming your application code is the source of truth for what gets served. If your CDN cache wasn't purged as part of the deploy that changed the image, this is very likely your actual problem, and no platform-side re-scrape will help until the edge cache itself is cleared.
Layer three: the image file's own URL, separate from the page
Even if the page's HTML correctly serves the new og:image URL, and even if a platform re-scrapes the page fresh, the image file itself can be cached separately if the URL didn't change. This happens when a workflow overwrites a file at a fixed path — replacing /images/og-default.png with a new file rather than publishing a new file at a new path. Browsers, CDNs, and some platform-side image caches can hold onto the old bytes at that URL independent of anything happening at the page level, because from a caching perspective, nothing about the URL itself signaled that the content changed. This is the single most preventable cause of 'og:image not updating,' and it's worth checking specifically: does your og:image URL change every time the image changes, or does it stay fixed while the file behind it gets swapped?
Why a fixed URL for a changing image is a design mistake, not just a caching annoyance
Caching exists because it's fast and cheap, and every layer in this chain — platform scrape caches, CDN edge caches, browser image caches — is caching aggressively on purpose. Fighting that with manual re-scrapes and cache-busting parameters treats the caching as an obstacle to work around each time, rather than fixing the actual mismatch: a URL is supposed to represent a specific, stable piece of content, and reusing the same URL for different content is what breaks every caching assumption built on top of it. The durable fix is giving each version of an image its own distinct URL, so caching can be as aggressive as it wants — an old cached copy is still correct, because the URL that was cached genuinely still points at the old content, and the new content simply lives at a new URL nobody's cached yet.
A subtler variant: the image updates for you but not for anyone else
One pattern that causes real confusion: you make the change, reload the page yourself, and the new image shows up fine — but a teammate, or a customer, or a share that was already posted, continues showing the old one. This isn't a contradiction, and it doesn't mean the fix is broken. Your own browser fetching the page fresh is a completely different request path than a platform's crawler, which may have scraped the page hours or days earlier and is serving its own stored result independent of what your browser sees right now. Similarly, a browser's local image cache can hold onto a previously loaded file at a given URL even after the server starts returning something different at that same URL, which is exactly the fixed-URL problem described above showing up client-side rather than platform-side. Confirming a fix 'worked' requires checking the actual sharing platform's cached view (via its debugger, if one exists) rather than trusting your own browser's rendering of the page.
When the fix is a versioning convention, not a technical setting
It's worth being explicit that fixing this properly is often more of a process change than a technical one. Teams that keep hitting stale og:image problems are often doing everything correctly at the infrastructure level — reasonable CDN settings, no unusual caching misconfiguration — but their content workflow still overwrites a file at a fixed filename every time an image updates, because that's the simplest way to think about 'replacing an image' and nobody's re-examined the assumption. Introducing a convention where every meaningfully different image gets a distinct filename or path (even something as simple as appending a date or a short hash) removes the entire category of bug without touching a single cache setting anywhere, because there's no longer a fixed URL for a cache to hold stale content against.
A diagnostic order to work through
- Load the raw page HTML directly and confirm og:image already reflects the new value, ruling out a deploy issue
- Check whether the image URL itself changed, or whether a fixed URL had its underlying file swapped
- If the URL is fixed, check CDN/reverse-proxy cache headers on that image path specifically
- Force a platform-side re-scrape (Facebook's debugger, LinkedIn's inspector) once the page and image are confirmed fresh
- For platforms without a debugger, use a cache-busting query parameter to guarantee a fresh fetch
- Confirm with an actual new share, not just a debugger's own display
How useopengraph avoids this class of bug entirely
This is the exact problem useopengraph's rendered image URLs are built to sidestep. Publishing a template creates a new version with its own immutable render URL under /api/render/{templateId}/v{version}/... — old versions never change, and a new publish always produces a new URL rather than overwriting the content behind an existing one. That means there's structurally no 'stale image at a fixed URL' failure mode to debug: every URL that's ever been cached, at any layer, by any platform, is still pointing at content that's genuinely still correct. When you do need to confirm what a platform currently sees for a given page, the Cache Debugger checks Facebook, X, LinkedIn, and other platforms live in one pass, and can trigger Facebook's own official re-scrape directly rather than requiring a separate cache-busting workaround.
Your browser fetching the page fresh is a completely different request path than a platform's crawler, which may have scraped the URL hours or days ago and is serving its own stored result. Confirm a fix through the platform's own cached view (its debugger, if one exists) rather than trusting how the page renders for you personally.
Just once, for that specific parameter value — it forces a fresh fetch on platforms without a public re-scrape tool, but it doesn't change the underlying pattern. If the workflow keeps overwriting a file at a fixed URL, you'll need a new cache-busting value every time the image changes rather than solving the problem at the root.
Facebook's Sharing Debugger and LinkedIn's Post Inspector both offer a direct re-fetch button. X, Slack, Discord, and iMessage don't publish an equivalent tool, so a cache-busting change to the URL is generally the only reliable way to guarantee a fresh fetch on those.
It works until something caches it — which, given platform scrape caches, CDN edges, and browser image caches, is essentially always. The durable fix is giving each meaningfully different image its own filename or path, even just a date or short hash appended, so there's no fixed URL for any layer to hold stale content against.
Stop paying per seat
for a usage-shaped problem.
Unlimited teammates, one usage pool. Start free with the scanner — no card required.