Broken images in your Instagram feed: causes and fixes

Your Instagram feed loads, the layout is there, but some tiles are gray squares or show a broken-image icon. That is a different problem from a feed that does not show at all, and it usually has a short list of causes. This guide explains how images reach your page, how to tell which cause you are looking at, and how to fix each one.

Updated October 12, 2026

Broken images vs. a missing feed

First, make sure you are reading the right article. If nothing at all appears where the feed should be, no header, no tiles, no “Powered by” line, the embed script itself did not run. That has its own causes, such as an unpublished widget, a website builder that strips scripts, or the monthly view limit. Our checklist Instagram feed not showing on your website? covers those.

This article is for the other case: the widget ran and drew its frame, but some or all of the photos are missing. Typical symptoms are:

  1. Gray squares where the photos should be. Each tile in Social Feed by grip space has a light gray background, so a tile whose image fails to load stays gray.
  2. A broken-image icon or a short line of text inside a tile. This is how your browser marks an image it could not load.
  3. Only some tiles are empty, usually one or two posts, while the rest look fine.
  4. The profile picture in the header is missing but the post tiles look fine, or the other way around.
  5. The tiles look fine, but the lightbox shows nothing or a video does not play when you open a post.

Whether it affects every tile or just a few is the most useful clue.

How images get from Instagram to your page

Knowing the path an image takes makes most of these problems easy to place. With Social Feed by grip space it works like this:

  1. Your page loads the embed script, a single script tag.
  2. The script asks Instagram, through Instagram’s official API, for your recent posts. Instagram replies with details for each post, including an address for its image (for videos, an address for the cover image and one for the video file).
  3. The script builds the feed in your page and sets each tile’s image to the address Instagram provided.
  4. Your visitor’s browser then loads each image directly from Instagram’s content delivery network (CDN). The images are not copied to our servers or to yours.

So the image request goes from the visitor’s browser to Instagram, under the rules of your page. Your security headers, a content blocker or your theme’s CSS can stop an image even when the feed works, and a change on Instagram’s side, such as a deleted post, changes what the image address returns.

One more detail: on the Free plan, the widget reuses the list of posts it fetched from Instagram for 24 hours, which is why new posts appear on your site about once a day. On the Light and Standard plans, the list is fetched fresh each time the feed is shown. You will see below why this can make a difference.

Find the cause in two minutes with developer tools

You do not need to be a developer. Every desktop browser has built-in tools that tell you why an image did not load.

  1. Open the page with the feed in Chrome, Edge or Firefox on a computer.
  2. Open the developer tools: press F12 on Windows, or Command+Option+I on a Mac.
  3. Click the Console tab and reload the page. Look for red error messages that mention an image address.
  4. Click the Network tab and reload the page again. Type cdninstagram or fbcdn into the filter box to show only requests to Instagram’s servers.
  5. Look at the Status column for each image. A normal image shows 200. Anything else, or a request marked as blocked, is your lead.

Here is how to read what you find:

What the tools showWhat it usually meansSection below
Console error mentioning “Content Security Policy” and img-srcYour site’s security policy does not allow Instagram’s image hostsContent Security Policy
Request status shows “(blocked:client)” or similar, or the request is missing entirelyA browser extension or content blocker stopped itContent blockers
Console error mentioning Cross-Origin-Embedder-Policy or “corp”Your site sends a strict cross-origin isolation headerCross-origin isolation
Status 403 or 404 for one or two imagesInstagram no longer serves that image address, often because the post was deleted or the address expiredDeleted or changed posts
All images return 200, but the tiles still look emptyThe images loaded; something on the page is hiding themTheme CSS
No request at all for images further down the gridThey have not been scrolled into view yet, or lazy loading never triggeredLazy loading

Only have a phone? Try a private window and a different network. If it works there, the cause is on your device or network, not your site.

Cause 1: the post was deleted, archived or changed on Instagram

Meta’s documentation for the Instagram Platform says its CDN URLs are “privacy-aware” and will not return the media when the content has been deleted or has expired. In other words, the image address for a post only keeps working while the post is still available and the address itself is still valid.

This is the most common reason for one or two broken tiles while the rest of the feed looks fine: you delete or archive a post, the widget still holds the earlier list of posts with the old image address, and Instagram declines to return the image.

On the Free plan, the widget reuses its list of posts for up to 24 hours, so a deleted post can remain in your feed, and appear broken, for up to about a day. When the list is next refreshed, the deleted post drops out and the rest of the feed shifts to fill the gap. On the Light and Standard plans, the list is fetched fresh each time the feed is shown, so a deleted post disappears from the feed on the next page load.

Fix: usually nothing; the problem clears itself at the next refresh. If you deleted a post on purpose and want it gone from a Free plan feed sooner, changing the widget’s number of posts, a filter or the video setting makes the widget fetch a fresh list right away, because it treats that as a new request. You can change the setting back afterwards. Our article on why your Instagram feed isn’t updating explains the refresh timing in more detail.

Cause 2: an image address expired before the page used it

Meta’s documentation also says CDN URLs stop returning media when they “have expired.” It does not publish how long an address stays valid, so we cannot give you a number, and we would be wary of anyone who does. What we can say is how this shows up in practice:

  1. A page left open for a long time. If a visitor opens your page, leaves the tab open and comes back much later, images that had not loaded yet, such as tiles further down a grid that load only when scrolled to, request addresses that were fetched when the page first opened.
  2. A list of posts reused for many hours. On the Free plan the widget reuses the same list of posts, including the image addresses, for up to 24 hours. If Instagram expires an address within that time, the tile can fail until the list is refreshed.

Ordinary page caching on your site does not cause this. The embed script is sent with headers telling caches not to store it, and the feed is built fresh in the browser on every page load.

Fix: reload the page. If the images load after a reload, an expired address was the cause, and real visitors arriving fresh are getting current addresses. If you are on the Free plan and see this regularly, the paid plans fetch a fresh list on every view, which removes the 24-hour window.

Cause 3: a Content Security Policy blocks Instagram’s image hosts

A Content Security Policy (CSP) is a security header that tells the browser which sites may supply scripts, images, videos and other resources to your page. Its img-src part controls images. MDN notes that if img-src is not set, the browser falls back to the default-src rule, so a strict default-src can block images even when nobody wrote an image rule on purpose.

A CSP problem affects every image from Instagram at once, and the Console shows an error saying the image violates the Content Security Policy. The layout usually still appears, because the script itself is allowed.

Instagram chooses which servers deliver its images. They often sit under subdomains of cdninstagram.com or fbcdn.net, and a policy that allows one exact hostname can break when Instagram switches servers.

Fix: add the hosts named in the Console error to img-src, preferably as a subdomain wildcard for the parent domain. Videos played in the lightbox need the same hosts in media-src. Our Content Security Policy guide for the Instagram widget has ready-to-copy examples for meta tags, Apache and nginx, plus a safe way to test changes.

The policy may come from a security plugin or your host rather than your own code; give the Console error to whoever manages it.

Cause 4: cross-origin isolation headers

This one is rare but breaks every image. Some sites send a Cross-Origin-Embedder-Policy (COEP) header for advanced browser features. MDN explains that with require-corp, a page can only load cross-origin images if the server sending them allows it with a Cross-Origin-Resource-Policy header; otherwise the browser blocks them. With credentialless, such images load without cookies instead. Feed images come from Instagram’s servers, and you cannot control which headers Instagram sends.

How to check: in the Network tab, click a failed image and look at the response headers, or look for a Console error that mentions Cross-Origin-Embedder-Policy. Then check your own page’s response headers for Cross-Origin-Embedder-Policy.

Fix: if you did not mean to enable it, remove the header. If you need it, credentialless may let third-party images load; test carefully, because it affects every cross-origin resource on the page. Otherwise, put the feed on a page without the header.

Cause 5: content blockers, privacy tools and network filters

Ad blockers, privacy extensions and some built-in browser protections block requests based on lists of domains. Some of these lists include domains owned by Meta, including the servers Instagram uses for images. When that happens, the feed’s frame may appear but the photos do not, or the whole widget may be blocked if the list also covers the script.

Signs that a blocker is the cause:

  1. The images are broken for you, but the feed looks fine for a colleague or on your phone.
  2. The images appear in a private window with extensions turned off.
  3. The Network tab shows the image requests as blocked by the client rather than returning an error code.
  4. The problem appears only on a certain network, such as an office or school network with a filtering proxy.

Fix: for your own browser, allow your site in the extension’s settings. You cannot change your visitors’ blockers, and you should not try to work around them; people who block Meta’s domains have chosen not to load content from them. The good news is that a blocked image affects only that visitor. Social Feed by grip space does not set cookies or use browser storage, and the rest of your page keeps working.

Cause 6: hotlink protection and referrer policies

Your own hotlink protection does not apply to Instagram images. Features such as Cloudflare’s Hotlink Protection block other websites from displaying images hosted on your site, by checking the Referer header of requests for your images. The images in your feed are hosted by Instagram, not by your site, so your hotlink setting never sees those requests. Turning it on or off makes no difference to the feed.

Your referrer policy is unlikely to be the cause. A Referrer-Policy header controls how much of your page’s address the browser sends with requests to other sites. MDN lists strict-origin-when-cross-origin as the browser default, which sends only your site’s origin to other HTTPS sites, and no-referrer, which sends nothing. We have not found anything in Meta’s documentation saying Instagram’s CDN requires a particular referrer, so we would not change your referrer policy without evidence. To rule it out, test once with the browser default.

Cause 7: theme or plugin CSS hides the images

Sometimes the developer tools show every image loading with status 200, and the tiles are still empty. Then the images arrived, but something on your page is hiding them.

The widget sets the size and position of its images with its own inline styles. A theme or plugin stylesheet can still override them, for example:

  1. A rule that applies to every image on the page with !important, such as forcing a height or a display value.
  2. An image optimization or lazy-loading plugin that makes images transparent until it adds its own class to them. Images added later by a script, like the ones in the feed, may never get that class.

How to check: right-click an empty tile and choose Inspect. The Elements panel highlights the image, and the Styles panel shows every rule applied to it. Rules that come from your theme or a plugin are labeled with their stylesheet’s file name. Look for opacity, visibility, display, width or height values that would hide the image.

Fix: exclude the feed from the plugin’s image handling, if the plugin offers exclusions, or narrow the theme rule so it does not target every image on the page. If you are not sure which rule is responsible, send us the page address and we can take a look.

Cause 8: lazy loading in tight spaces

In a grid, the widget loads the first row of images right away and lets the browser load the rest as visitors scroll near them. In a slider, all images load right away so that swiping never reveals an empty tile.

MDN notes that a lazy-loaded image that is never near the visible part of the page is never loaded. That is the intended behavior, but it can look like a fault in two situations:

  1. The feed sits in a hidden container, such as a closed tab, an accordion or a popup that opens later. Images further down may not load until the container is shown and scrolled.
  2. You take a screenshot of a long page with a full-page screenshot tool. Tiles that were never scrolled into view can appear gray in the screenshot even though they load normally for real visitors.

Fix: scroll to the feed on the live page; if the tiles fill in as you approach them, nothing is wrong. If the feed lives inside a tab or accordion and you want everything ready the moment it opens, a slider layout loads all images up front. Our article on lazy loading an Instagram feed explains the trade-offs.

What is not a broken image

A few things look like missing images but are expected behavior:

What you seeWhat is happening
A video tile shows its cover image but has no play buttonInstagram did not provide the video file, which it does for some videos, such as Reels with copyrighted or licensed audio. Meta’s documentation says the media_url field is omitted for media with copyrighted material. The widget shows the cover image and does not offer playback it cannot deliver.
A post you can see on Instagram is not in the feed at allThis is not a broken image. Either a filter excludes it, the post count is already full, Instagram provided no image for it (the widget skips such posts), or, on the Free plan, it is newer than the last daily refresh.
A carousel tile shows only one imageTiles always show the first image of a carousel. Visitors can browse all images in the lightbox if you turn that on.

For more on videos specifically, see showing Instagram videos on your website. For image quality, see Instagram image sizes for websites.

Quick reference: symptoms and fixes

SymptomMost likely causeWhat to do
One or two gray tiles, the rest fineDeleted, archived or changed post; expired addressReload. On Free, wait for the daily refresh or change a setting to refresh now.
Every image gray, header and layout fineCSP img-src, COEP, or a blockerCheck the Console for a CSP or COEP error; test in a private window.
Broken only for youBrowser extension or network filterTest with extensions off and on another network.
Images return 200 but tiles look emptyTheme or plugin CSSInspect a tile and look for rules hiding the image.
Tiles fine, lightbox video will not playCSP media-src, or no video file from InstagramCheck the Console; see the videos article.
Nothing appears at allThe script did not runSee the not-showing checklist.

Frequently asked questions

Do I need to re-paste the embed code to fix broken images? No. The embed code does not contain any image addresses; it only loads the script, which fetches current addresses from Instagram. Re-pasting the same code changes nothing.

Will reconnecting my Instagram account fix broken images? Usually not. If the connection had stopped working, the feed would not show new posts at all, rather than showing some broken images. Reconnecting helps when the feed stops updating, not when a single image fails. Our article on expired Instagram access tokens explains how connections are kept alive.

Does a broken image count as a view? Views are counted when the widget is shown on a page, regardless of whether each image loads. A view is one display of the widget, not one image.

Can the widget show a placeholder instead of a gray square? At the moment, a tile whose image fails to load keeps its light gray background. There is no setting to replace it with a custom image.

I checked everything and images are still broken. Email us at info@grip-space.co.jp with the page address, the browser you used, and, if you can, a screenshot of the Console and Network tabs. We will look at it with you.

Related reading

If the feed does not appear at all, start with Instagram feed not showing on your website?. For security headers, see the Content Security Policy guide. For update timing on each plan, see what you get on the free plan and the pricing section. Setting up a new feed? Our guides cover WordPress, Shopify, Wix, Squarespace, Webflow and plain HTML, or you can sign up for free.

Sources

  1. Meta for Developers, “Overview of the Instagram Platform” (Content Delivery Network URLs): https://developers.facebook.com/docs/instagram-platform/overview/
  2. Meta for Developers, “IG Media” reference (media_url and thumbnail_url): https://developers.facebook.com/docs/instagram-platform/reference/instagram-media/
  3. MDN Web Docs, “CSP: img-src”: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/img-src
  4. MDN Web Docs, “Cross-Origin-Embedder-Policy”: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cross-Origin-Embedder-Policy
  5. MDN Web Docs, “Referrer-Policy”: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Referrer-Policy
  6. MDN Web Docs, “The Image Embed element”: https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/img
  7. Cloudflare Docs, “Hotlink Protection”: https://developers.cloudflare.com/waf/tools/scrape-shield/hotlink-protection/
  8. Chrome for Developers, “Inspect network activity”: https://developer.chrome.com/docs/devtools/network

Get your embed code in a few minutes. The Free plan needs no credit card.

Sign up free