More fixes

WordPress images not showing

Your gallery shows grey boxes, a small broken-picture icon, or nothing at all where the photos used to be. The photos are usually still fine; what breaks is the address the page asks for, or the step that is meant to load it. One check on a single broken image tells you which. Below is a rebuilt example (not a real client), that check, and the fix for each answer.

The gallery page

What the checks found


  

First: ask one broken image what went wrong

  1. Right-click the broken image and choose "Open image in new tab" (or "Copy image address" and paste it). Read the address before anything else: does it start with your current domain and https://? An old domain, a staging address or http:// is already the answer.
  2. See what the new tab shows. A "Not Found" page means the file is not at that address. "Forbidden" or "Access denied" means it is there but the server refuses it. If the photo opens fine on its own, the file is OK and something on the page is stopping it (the last two causes).
  3. For more detail, press F12, open the Network tab, choose the Img filter and reload. Each picture is a row with a status: 404 (missing), 403 (refused), (blocked:mixed-content), or a red row naming another site. Pictures with no row at all were never requested, which points at a lazy-load script. The Console tab names any script error.

The causes, most common first

  1. The site moved and the image addresses did not. After a move to a new host, a new domain or https://, posts still point at the old addresses, because WordPress stores the full address of every image inside the post text. Fix it with a search-and-replace across the database (the Better Search Replace plugin, or wp search-replace if you have WP-CLI): old address to new, a dry run first, and a backup before the real run. Do not edit the database by hand with a text editor: some values carry their own length, and a plain edit breaks them.
  2. The files never arrived. A move or a restore copied the database but not the wp-content/uploads folder, or only part of it. The Media Library still lists the photos (that list lives in the database) but every one is a 404. Copy the uploads folder again from the old host or the backup, keeping the year and month folders as they were.
  3. Upper and lower case changed. Windows servers treat Shop.JPG and shop.jpg as the same file; Linux servers do not. After a move from one to the other, the images whose names differ only in case go missing. Rename the files to match the addresses, or update the addresses.
  4. The server refuses the folder. A 403 on every image usually means the permissions on wp-content/uploads were changed (a security plugin, a host move, a hand-made change). Folders should normally be 755 and files 644; many hosts have a "fix permissions" button. A stray .htaccess inside uploads that denies everything does the same.
  5. Hotlink protection blocks your own site. cPanel's Hotlink Protection and Cloudflare's Hotlink Protection stop other sites showing your pictures, but a list that names only example.com also blocks www.example.com, your CDN, or Google Images. Add every version of your own address, or switch it off to test.
  6. A CDN or image plugin rewrote the addresses. Jetpack's Site Accelerator, Smush, Optimole, ShortPixel, EWWW and similar plugins swap image addresses for their own server, or for a .webp copy. If that copy was never made, or the account ran out, the swapped image fails while the original file is fine. Switch the plugin's CDN or WebP rewrite off; if the photos come back, regenerate its copies or contact the plugin's support.
  7. Lazy loading never finished. To save data, the page holds the real address in a spare slot (data-src) and a script moves it in when you scroll. If that script is broken, delayed or loaded twice (the theme, a speed plugin and WordPress all lazy-load), the swap never happens and you see placeholders. Turn off lazy loading and any "delay JavaScript" option in your speed plugin, one at a time, until the photos appear; keep one lazy loader, not two.
  8. Thumbnails were never made. The full-size photo exists, but the smaller sizes the theme asks for do not (a new theme, a failed upload, or a server with no image library). The Regenerate Thumbnails plugin rebuilds them. If new uploads still come out without sizes, ask the host whether the GD or Imagick PHP extension is installed.

What you see, what it means, what it needs

What you seeUsual causeUsual fix
Image address names an old domain, a staging site or http://Site moved, addresses did notDatabase search-and-replace, dry run and backup first
Image opens on its own as "Not Found"Uploads not copied, or a name changed caseCopy wp-content/uploads again; match file names
"Forbidden" or 403 on every imageFolder permissions or hotlink protectionFolders 755, files 644; add your own addresses to the hotlink list
Address ends in .webp or points at a plugin's serverCDN or WebP rewrite with no copy behind itSwitch the rewrite off, regenerate the copies
Grey placeholders, no image requests in the Network tabLazy-load script broken or doubledOne lazy loader; switch off "delay JavaScript" to test
Full-size photo fine, small versions missingThumbnails never generatedRegenerate Thumbnails; ask the host about GD or Imagick
Photos fine for you, broken for visitorsAn old cached page with old addressesClear the caches, then check in a private window

What not to do

Once one broken image has told you its status, the fix is usually minutes. If you would rather hand it over, or the photos still will not show, that is what the box below is for. Related: a photo that will not upload, a site slow because of big photos and changes that do not show on the live site (an old cached page can carry old image addresses too).