Why images aren't loading on my site — 3 causes, starting with letter case

Locally the site looks picture-perfect. You deploy, open it — and instead of photos, gray broken icons. Here's the surprise that explains half of these cases: on your computer Photo.JPG and photo.jpg are the same file, but on the server they're two different ones. macOS and Windows ignore letter case in file names; a Linux server doesn't. The image went "missing" because of a single capital letter. Let's take that cause and two more, in order of frequency.
Cause 1: the path or the case doesn't match
The browser looks for the file by the exact string in src. Any mismatch — a space, .JPG instead of .jpg, Images/ instead of images/ — and the file "doesn't exist."
How to check. Right-click the spot where the image should be → "Open image in new tab." Seeing a 404 means no file exists at that address. For the full picture, open DevTools → the Network tab, refresh the page and look at the status codes next to your images: 404 — not found, 403 — forbidden.
How to fix. Compare the path character by character against the real file name. Then adopt the rule that kills this problem forever: all files lowercase, no spaces, no special characters — hero-photo.jpg, not My Site Photo (1).JPG. This is a classic of the "works locally, breaks on the server" genre — the local file system forgives, the server's doesn't.
Cause 2: the file simply isn't on the server
Path is correct, but the image is still a 404? Then the file never made it to the server. Typical scenarios:
- The image sits in the wrong folder. Most build tools (Vite, Next.js and others) serve static files only from a special folder — usually
public/. A file next to your code but outside it doesn't make the build. - The file is not committed: you forgot to add it to git, or the media folder landed in
.gitignore. It exists on your disk, not in the repository — and the deploy shipped without it. - The file was added after the deploy — the new version of the site simply isn't out yet.
How to check. Look at your repository on GitHub: is the file where the path expects it? Not in the repo — won't be on the server.
How to fix. Put the image in the static folder, commit, redeploy. And if images are uploaded by your users, they don't belong in the repository at all — that's what storage is for; how to wire up file uploads is covered step by step.
Cause 3: the image is someone else's — and their server objects
You pasted a direct link to an image on another site. On your machine it showed up (the browser had it cached), but your visitors get nothing.
How to check. In Network the image has status 403, yet it opens fine by direct URL in a separate tab. That's hotlink protection: the other server sees the request coming from your site and refuses — it's their bandwidth. Second variant: the link starts with http:// while your site is on https:// — the browser silently blocks the mix, and the error only shows in the console.
How to fix. Don't link to other people's servers. Download the image (if the license allows) and put it in your own public/ or your own storage. That also kills the http:// problem — everything from your own domain travels over https://.
The 30-second checklist
- Open the image by direct URL → what's the status?
- 404 → check path and case; does the file even exist in the repository?
- 403 → the image is someone else's: move it to your side.
- Opens fine but blank on the site → check the console: the blocking reason is there.
Why does the image load, but painfully slowly?
Most likely you dropped in a photo straight from a phone — 4–8 MB per frame. Resize it to the size you actually display and convert to WebP: the weight drops several times over with no visible loss. At real traffic, a CDN — a network of copies closer to the visitor — helps on top.
What does it mean when text shows instead of the image?
That's the alt text — the fallback description the browser draws when the file failed to load. It's not the error itself, it's a symptom: walk the checklist above and check the status code.
Short story-lessons, an agent simulator and daily practice — in our mobile app. Free.





