ScreenshotNeo

BlogHow-to

How to Add an Image to a Website

Add images with accessible HTML, responsive sizing, srcset, picture, troubleshooting, and a ScreenshotNeo option for generated captures.

By the ScreenshotNeo team1 October 20269 min read

The standard way to add an image to a website is an HTML <img> element with a valid src and useful alt text:

<img src="images/photo.jpg" alt="A red bicycle leaning against a brick wall">

The src value points to the image file. Use a relative path for a file in your site, or an absolute HTTPS URL for an image hosted elsewhere. The alt value is the text alternative used by screen readers and shown when the image cannot load. See the MDN <img> reference.

1. Add a local image with HTML

Put this structure in a simple site:

my-site/
├── index.html
└── images/
    └── bicycle.jpg
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Product photos</title>
</head>
<body>
  <h1>Bicycle collection</h1>
  <img
    src="images/bicycle.jpg"
    alt="A red bicycle leaning against a brick wall"
    width="1200"
    height="800"
  >
</body>
</html>

Paths are resolved from the URL of the HTML document. If index.html is in the site root, images/bicycle.jpg means a file in the root-level images directory. From products/item.html, the same root-level file would usually be ../images/bicycle.jpg. File names and directory names are often case-sensitive on production servers.

Absolute URLs

<img
  src="https://cdn.example.com/catalog/bicycle.jpg"
  alt="A red bicycle leaning against a brick wall"
>

The remote server must allow the browser to fetch the image over HTTPS. An image URL that requires a private login, blocks hotlinking, or returns HTML instead of image bytes will not render.

2. Write useful alternative text

W3C WAI states: “Images must have text alternatives that describe the information or function represented by them.” Choose the text from the image’s purpose and its surrounding content. The WAI Images Tutorial and H37 technique provide the accessibility guidance.

Image role What to write Example
Informative State the important information conveyed by the image. alt="Bar chart showing sales rising from January to June"
Decorative Use an empty value so assistive technology can skip it. alt=""
Functional Describe the action or destination, not the pixels. alt="Open the account settings"
Complex chart or diagram Use a short identifying alt and provide the detailed explanation in nearby text. alt="System architecture diagram" plus a textual description

Do not repeat information already stated immediately beside the image, add phrases such as “image of” unnecessarily, or leave meaningful images with an empty alt value. A linked image needs alt text describing what activating the link does:

<a href="/account">
  <img src="icons/account.svg" alt="Open your account">
</a>

3. Reserve space with width and height

Use the image’s actual intrinsic dimensions. The browser can reserve the aspect ratio before the file arrives, reducing layout movement:

<img
  src="images/photo.jpg"
  alt="A red bicycle leaning against a brick wall"
  width="1200"
  height="800"
>

These attributes describe the source dimensions; they do not force the image to display at 1200 pixels on every screen. CSS controls the rendered size.

4. Make images responsive

img {
  max-width: 100%;
  height: auto;
  display: block;
}

max-width: 100% lets an image shrink to its container while height: auto preserves its proportions. Keep the intrinsic width and height attributes as well. This is the pattern described by W3C’s advisory C37 technique.

For a contained image with a maximum reading width:

.article-image {
  width: 100%;
  max-width: 800px;
  height: auto;
  margin-inline: auto;
}

WCAG 2.2’s Reflow criterion uses a 320 CSS pixel viewport width as a test threshold (and 256 CSS pixels for height). Check that the image and its container do not create unwanted horizontal scrolling at narrow widths.

5. Serve different image sizes with srcset and sizes

If you have several resolutions of the same image, provide width candidates:

<img
  src="images/landscape-800.jpg"
  srcset="images/landscape-400.jpg 400w,
          images/landscape-800.jpg 800w,
          images/landscape-1600.jpg 1600w"
  sizes="(max-width: 600px) 100vw, 800px"
  width="1600"
  height="1000"
  alt="Snow-covered mountain reflected in a lake"
>

srcset lists available files and their intrinsic widths. sizes tells the browser how wide the image is expected to appear. The browser chooses a suitable candidate based on those hints and current conditions. Do not mix width descriptors (w) and pixel-density descriptors (x) in one srcset.

For a fixed display size with density variants, use pixel-density descriptors instead:

<img
  src="images/avatar.png"
  srcset="images/avatar.png 1x, images/avatar@2x.png 2x"
  width="96"
  height="96"
  alt="Jordan Lee"
>

6. Use <picture> for formats or art direction

Use <picture> when the source itself should change, such as an alternate crop or format:

<picture>
  <source
    type="image/avif"
    srcset="images/hero.avif 800w, images/hero-large.avif 1600w"
    sizes="100vw"
  >
  <source
    type="image/webp"
    srcset="images/hero.webp 800w, images/hero-large.webp 1600w"
    sizes="100vw"
  >
  <img
    src="images/hero.jpg"
    alt="A mountain lake at sunrise"
    width="1600"
    height="900"
  >
</picture>

The nested <img> is the fallback and carries the alt text. Use media conditions for art-directed crops:

<picture>
  <source media="(max-width: 600px)" srcset="images/portrait-crop.jpg">
  <img src="images/wide-crop.jpg" alt="A runner crossing the finish line" width="1600" height="900">
</picture>

7. Images in common HTML contexts

Figure and caption

<figure>
  <img src="images/diagram.png" alt="Request flow from browser to image server" width="1200" height="700">
  <figcaption>The request passes through the image service before the browser displays the result.</figcaption>
</figure>

Background images

.hero {
  background: url("/images/hero.jpg") center / cover no-repeat;
}

CSS backgrounds are appropriate for decoration. If the background conveys information, use an HTML image or provide an equivalent text alternative; CSS alone does not give screen readers a useful alt value.

Lazy loading

<img
  src="images/gallery-12.jpg"
  alt="A ceramic bowl on a wooden table"
  width="1200"
  height="800"
  loading="lazy"
  decoding="async"
>

Lazy-load images below the initial viewport when it helps page weight. Keep the main above-the-fold image eager unless you have a specific reason to defer it.

8. Check image files and delivery

  • Use a format supported by your target browsers and pipeline, such as JPEG for photographs, PNG for lossless transparency, SVG for scalable vector artwork, and WebP or AVIF when your delivery setup supports them.
  • Export dimensions close to the largest size actually displayed. Sending a 6000-pixel original into a 400-pixel card wastes bandwidth.
  • Serve images over HTTPS and configure long-lived caching for versioned files.
  • Confirm the response has an image content type such as image/jpeg, image/png, image/webp or image/svg+xml.
  • Keep filenames URL-safe. Encode spaces or rename files to avoid path and deployment differences.

9. Troubleshooting

Symptom Likely cause Fix
Broken-image icon Wrong relative path, filename case, or missing deployed file Open the exact image URL in a browser, inspect the Network panel, and compare the path character by character.
404 response The server cannot find the requested resource Correct the directory level (./, ../, or root-relative path) and deploy the file.
403 response Private object, hotlink protection, or authorization requirement Make the asset readable to site visitors or serve it through an authorized image endpoint.
Image downloads instead of displaying Incorrect Content-Type or download disposition Configure the server to return the correct image media type and inline content.
Image is stretched Both dimensions are forced independently Set one dimension to auto; include accurate intrinsic width and height.
Horizontal scrolling on phones Fixed width exceeds the viewport Apply max-width: 100%; height: auto and test at 320 CSS pixels.
Screen reader says “image” with no meaning Missing or empty alt on an informative image Write concise purpose-based alt text.
Decorative image is announced Decorative image has descriptive alt text Use alt="" when it adds no information.
Wrong responsive file Incorrect sizes, mixed descriptor types, or inaccurate file widths Check the rendered CSS width, use only one descriptor type, and verify each candidate’s real dimensions.
Slow page Oversized files, too many images, or no caching Resize and compress assets, use responsive candidates, lazy-load below-fold images, and cache versioned files.

10. Capture a website image with ScreenshotNeo

If your goal is to place a current webpage snapshot into another site, you can capture the source page instead of maintaining a browser automation setup. ScreenshotNeo is a website screenshot API and MCP server. It accepts one GET request and returns PNG, JPEG, WebP, or PDF. Cookie and consent banners, newsletter popups, and chat widgets are removed before capture; bot checks, blank pages, failed loads, timeouts, and cache hits are not billed. Responses identify the page verdict and billing status with X-Page-Verdict and X-Billed headers.

See the ScreenshotNeo API documentation for the full parameter list. The same service supports full-page captures with lazy images loaded, CSS-selector element captures, dark mode, device presets and custom viewports, retina scale, PDF paper settings, custom CSS and JavaScript, clicks, waits, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, TTL caching, signed image links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, usage reporting, and an OpenAPI specification.

cURL

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

Python

import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)

Node.js

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot failed: ${res.status}`);
const buffer = Buffer.from(await res.arrayBuffer());
require('node:fs').writeFileSync('shot.webp', buffer);

Insert the returned file

<img
  src="/captures/stripe.webp"
  alt="Screenshot of the Stripe homepage"
  width="1600"
  height="1000"
>

For a public <img> tag, use a signed link. For repeated captures, choose a cache TTL; for many URLs, use the bulk endpoint. An MCP server provides take_screenshot, get_page_info, and capture_pdf tools to Claude, Cursor, and other MCP clients.

Or skip the browser setup

Use the one-call API example above when you need a maintained capture service. Cookie banners, popups, and chat widgets are removed before the shot. Bot checks, blank pages, and failed loads are never billed. The MCP server lets AI agents take screenshots. The Free plan includes 1,000 screenshots a month with no card, and paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.

11. Performance, reliability, and cost checklist

  • Performance: provide actual dimensions, select an appropriate source with srcset, avoid oversized originals, and lazy-load images below the fold.
  • Reliability: test production URLs, case-sensitive paths, fallback formats, and slow or blocked networks. Keep meaningful alt text so the page still communicates when an image fails.
  • Accessibility: decide whether the image is informative, decorative, functional, or complex before writing alt text. Test keyboard and screen-reader flows for linked images.
  • Capture cost: ScreenshotNeo bills only clean shots; bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing. Use caching and bulk capture where they fit your workload.

12. Final checklist

  • The src URL returns the intended image.
  • The alt value matches the image’s purpose; decorative images use alt="".
  • Intrinsic width and height are accurate.
  • CSS prevents overflow and preserves the aspect ratio.
  • srcset and sizes use matching, verified candidates when needed.
  • The image remains understandable if it cannot load.
  • The page works at narrow widths and with assistive technology.

FAQ

Can I add an image without CSS?

Yes. A valid <img> element works without CSS, though responsive CSS is recommended for images that must fit different screens.

Should every image have alt text?

Every <img> should have an alt attribute. Use meaningful text for informative or functional images and an empty value for purely decorative images.

Is a URL in src enough?

It is enough for a basic image if the URL is publicly fetchable and returns a supported image file. Add dimensions, responsive candidates, and appropriate alt text as the page requires.

When should I use <picture> instead of srcset?

Use srcset for different resolutions of the same image. Use <picture> when the format, crop, or source should change.

Can ScreenshotNeo return an image I can embed?

Yes. The API returns PNG, JPEG, or WebP bytes, and signed links are available for public image tags.