ScreenshotNeo

BlogHow-to

How to Fix an HTML Image Source That Won’t Display a PNG

Diagnose a missing PNG by checking its URL, network response, MIME type, responsive source, CORS behavior, and file integrity—in that order.

By the ScreenshotNeo team29 September 20269 min read

How to Fix an HTML Image Source That Won’t Display a PNG

A PNG that does not appear in an HTML page is not always an HTML syntax problem. The browser may be requesting the wrong path, receiving an error or non-image response, choosing a different URL from srcset, blocking a cross-origin request, or receiving damaged or mislabeled bytes. Diagnose those layers in order: verify the deployed URL, inspect the actual request and response, check responsive-image selection and CORS, then validate the file.

A .png suffix does not prove the response contains valid PNG data. Check the requested URL, HTTP status, response body and Content-Type before changing markup. The steps below use browser developer tools and small runnable checks to narrow down the cause.

1. Verify the source path and deployed file

Start with the URL in the rendered page, not just the path you intended to write. A relative URL is resolved from the document’s URL. For example, if the page is https://example.com/articles/page.html, then images/photo.png resolves under /articles/images/, not necessarily the site root.

<img src="images/photo.png" alt="A description of the image">

Check the filename, capitalization, extension, and directory. Many production file servers distinguish Photo.png from photo.png, even if your development machine’s filesystem does not. A typo like unicorn_pics.png when the real file is unicorn_pic.png is enough to break the image.

  1. Inspect the HTML or DOM and copy the exact value of src.
  2. Resolve that value against the page URL. For a root-relative path, begin at the domain root; for a relative path, begin at the page’s directory.
  3. Open the resulting image URL directly in a new tab. If it returns a 404, a login page, or another page instead of the image, fix the path, deployment, or access rules.
  4. Confirm the asset exists in the directory or storage bucket actually deployed. A file present locally may not have been included in the build or upload.

When a page works locally but not after publishing, compare the production URL and deployed filenames. Also check whether the build pipeline changes asset paths or hashes them. Use the URL emitted in the deployed HTML; do not assume a local path still applies.

2. Inspect the browser’s image request

Open developer tools, choose the Network panel, reload the page, and filter for images or search for the filename. Select the request and inspect its URL, status, response headers, and preview or response content. This shows what the browser actually fetched, which may differ from what you expected from the source markup.

Trace the image from the resolved URL through the HTTP response to the rendered page.
Trace the image from the resolved URL through the HTTP response to the rendered page.
Evidence What it suggests Next step
No image request The element may not be in the rendered DOM, may be lazy-loaded, or may use a different responsive candidate. Inspect the element, scroll it into view, and check srcset and JavaScript behavior.
404 or similar failure The URL is wrong or the deployed asset is missing. Correct the path or deploy the file at the requested location.
200 response The HTTP request succeeded, but the body might still be HTML, invalid data, or a damaged image. Inspect the response headers and preview; open the URL directly.
304 response The browser reused a cached representation after validation. Usually normal. If you suspect stale content, disable cache in developer tools and reload.
Blocked or failed request A network, policy, access, or cross-origin issue may be involved. Read the Console message and inspect the request’s initiator and headers.

A successful status such as 200 only confirms an HTTP-level success. It does not certify that the response body is a PNG. A server may return an HTML error page with status 200, for example, so inspect the response preview and headers too.

3. Check the response Content-Type

A PNG response should be served with Content-Type: image/png. Browsers use media type information to interpret the response; they do not simply trust that a URL ending in .png contains PNG bytes. If the server returns text/html, a generic type, or an unrelated image type, correct the server, object storage metadata, or application response configuration for that asset.

HTTP/1.1 200 OK
Content-Type: image/png

Check the response header in the Network panel. The exact fix depends on the host: a static file server, CDN, object store, and application endpoint may each set the type differently. Do not change the extension to hide a mismatch; serve the correct content with the correct type. Also make sure a redirect has not sent the request to a page that returns HTML.

4. Confirm which responsive image URL was selected

If the element has srcset, the requested URL may not be the one in src. With width descriptors such as 400w and 1200w, browsers that support srcset select a candidate using the candidates and the sizes value; the src fallback is ignored for that selection.

With srcset, inspect the selected candidate rather than assuming the browser used src.
With srcset, inspect the selected candidate rather than assuming the browser used src.
<img
  src="images/photo-800.png"
  srcset="images/photo-400.png 400w, images/photo-1200.png 1200w"
  sizes="(max-width: 600px) 100vw, 800px"
  alt="A description of the image">

In developer tools, inspect the rendered element’s currentSrc property or the Network request URL. Then verify that exact candidate exists and returns a valid image. A stale generated filename or incorrectly configured CDN path in one candidate can make the image fail only at particular viewport sizes or device pixel ratios.

For a quick console check, select the image element in the Elements panel so it is available as $0, then run:

$0.src
$0.currentSrc

src shows the attribute URL after browser resolution; currentSrc shows the selected candidate. If there is no srcset, they will normally refer to the same source.

5. Check cross-origin behavior and CORS

An image hosted on another origin can generally be displayed as an image without adding a crossorigin attribute. That attribute changes the request to use CORS. If it is present, the remote server must allow the page’s origin for the image request to succeed; otherwise, the browser blocks it and reports a CORS error in the Console.

Inspect the Console and the response’s CORS headers. If the image only needs to appear on the page, remove an unnecessary crossorigin attribute and retry. If your code needs to read image pixels through a canvas without tainting it, keep the CORS request and configure the image server to grant access to the required origin. CORS is enforced by the browser; changing local HTML cannot make a remote server grant permission.

<!-- For display only, no CORS attribute is usually needed -->
<img src="https://cdn.example.com/photo.png" alt="A description">

<!-- For use with canvas, the image server must allow this origin -->
<img crossorigin="anonymous" src="https://cdn.example.com/photo.png" alt="A description">

6. Validate the file itself

If the URL, status, and headers look right, verify the response is a real, readable PNG. Files can be truncated during upload, corrupted, or renamed from another format. The PNG signature begins with the bytes 89 50 4E 47. Most authors can first check the file with an image viewer or trusted image tool; if that tool cannot open it, re-export or replace the asset from a known-good source.

For a command-line check on a local file, use a file identification utility if available:

file public/images/photo.png

The output should identify a PNG image. This is a local inspection; for a hosted asset, download the response you inspected in the Network panel and check that copy. Avoid assuming that a successful download or a .png name means the bytes are intact.

7. Preserve useful alternative text

Give informative images meaningful alt text. If the image fails, that text conveys its purpose to people using assistive technology and may be visible in the page. Use alt="" only for decorative images that add no information. Since browsers may hide the broken-image icon for an image with empty alt text, decorative-image failures can also be less obvious during visual debugging.

8. Use a screenshot to inspect the rendered result

Once the request succeeds, inspect the page at the viewport where the issue was reported. The image might load but be hidden by CSS, clipped by an ancestor, covered by another element, or rendered at zero size. Check computed styles for display, visibility, opacity, dimensions, and overflow. Compare the page at a narrow and wide viewport if it uses responsive markup or styles.

A screenshot can help you capture the exact viewport for a bug report or compare a page before and after a change. It does not replace checking Network and Console: a screenshot shows the rendered outcome, while those panels help identify why it happened.

9. Troubleshooting checklist

Symptom Likely cause Fix
Broken image icon and 404 Typo, wrong relative directory, capitalization mismatch, or missing deployed file. Use the requested URL from Network, correct it, and confirm the asset is deployed there.
200, but image remains broken Response is HTML or invalid/corrupt image data. Inspect the body and open or validate the downloaded file.
Wrong image appears only at some sizes srcset selected a different, stale candidate. Check currentSrc, sizes, and each candidate URL.
Console reports CORS crossorigin triggers a CORS request, but the image server does not allow it. Remove the attribute if only displaying; configure the server if canvas access is required.
Response has an unexpected type Server or storage metadata is misconfigured, or a redirect served a page. Return the asset with Content-Type: image/png and inspect redirect targets.
Works locally, fails in production Asset was omitted, path casing differs, or the deployed base path changed. Inspect deployed HTML and confirm the file exists at the production URL.
Image request succeeds but nothing is visible CSS hides, clips, or collapses the element. Inspect computed styles and ancestor layout in developer tools.

10. Performance, reliability, and cost considerations

For this diagnosis, the browser’s Network and Console panels are the primary evidence and do not require a paid service. Reloading with cache disabled can help distinguish stale cached content from a current server response, but remember that a normal 304 is a valid cache revalidation result. Avoid repeatedly adding cache-busting query parameters to production URLs without understanding how your CDN or application caches them.

For reliability, check the image URL from the same environment and page origin where users encounter the failure. A local file viewer cannot reveal a production 404, a CORS rejection, or a responsive candidate mismatch. Conversely, a screenshot of the page cannot prove that a PNG response has the right MIME type or valid bytes. Use each tool for the evidence it provides.

Or skip the browser setup

For a captured view of the page while investigating, ScreenshotNeo provides a one-request screenshot API. See the ScreenshotNeo API documentation for request options. This captures the page view; use browser developer tools for request headers and CORS diagnostics.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://example.com"},
    timeout=90,
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));

ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before capture. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed; the response includes X-Page-Verdict and X-Billed headers. Its MCP server lets AI agents use take_screenshot, get_page_info, and capture_pdf. The free plan includes 1,000 screenshots each month with no card; paid plans start at $5 for 3,000 shots.

Sign up for 1,000 free screenshots a month, with no card.

FAQ

Does the PNG extension guarantee the file is a PNG?

No. The URL extension is only part of the name. Check the response type and actual bytes; the server can return a different format or an HTML page at a URL ending in .png.

Why does the image work on my computer but not after deployment?

The deployed file may be missing, its capitalization may differ, or the production page may resolve the relative path from a different directory. Inspect the production request URL and confirm that exact asset is deployed.

Can I fix CORS by changing the image URL in HTML?

Only if you switch to a server that grants the required access. The remote image server must permit the page origin when the request uses CORS, such as when canvas access is needed.

Should every image have nonempty alt text?

No. Informative images need text describing their relevant content or purpose; purely decorative images should use empty alt text.