October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run ScanOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
CORS

How to Build a Website That Displays Random Screenshots

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use a curated array of screenshot records, choose one with a random index, and assign its URL to an <img> element. Store each image’s alt text and dimensions alongside its path, provide a “Show another” control, and display a fallback when loading fails. This pattern works with local files or permitted remote URLs without downloading image bytes into JavaScript.

Choose the screenshot source before writing code

A random-image page is only as dependable as its image collection. For a small site, keep screenshots in your own project and maintain a list of paths. Local assets give you control over availability, filenames, dimensions and caching. Remote assets reduce your deployment bundle but can be renamed, removed, blocked from hotlinking or served under terms that do not permit reuse.

Confirm permission to copy or embed every screenshot. The browser references an image; it does not grant you rights to the underlying content. The browser-security references below explain loading behavior, not licensing for any particular screenshot source.

Use a metadata record for every image

Keeping metadata with each URL lets you provide useful alternative text and reserve layout space. The MDN <img> reference describes the element as embedding an image in the document and notes that alt is mandatory and useful to screen-reader users.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
const screenshots = [
  {
    src: "/screenshots/dashboard.webp",
    alt: "Analytics dashboard showing weekly traffic",
    width: 1600,
    height: 1000
  },
  {
    src: "/screenshots/mobile-checkout.webp",
    alt: "Mobile checkout form with order summary",
    width: 1170,
    height: 2532
  },
  {
    src: "https://cdn.example.com/landing-page.jpg",
    alt: "Landing page with a blue call-to-action panel",
    width: 1440,
    height: 900
  }
];

Use root-relative paths such as /screenshots/file.webp when the files are served by the same site. A relative path such as screenshots/file.webp is resolved relative to the current page URL, which can be surprising on nested routes.

Build the basic random screenshot page

The following complete example selects an image when the page loads and whenever the visitor activates a button. It also updates the accessible status text, sets intrinsic dimensions, and shows a visible fallback if the request fails.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Random screenshot</title>
  <style>
    .frame { max-width: 900px; margin: 2rem auto; padding: 1rem; }
    .frame img { display: block; width: 100%; height: auto; }
    .error { color: #9b1c1c; }
  </style>
</head>
<body>
  <main class="frame">
    <h1>Random screenshot</h1>
    <button id="another" type="button">Show another</button>
    <p id="status" role="status" aria-live="polite"></p>
    <figure>
      <img id="shot" alt="" width="1" height="1">
      <figcaption id="caption"></figcaption>
    </figure>
    <p id="error" class="error" hidden>This screenshot could not be loaded.</p>
  </main>
  <script>
    const screenshots = [
      { src: "/screenshots/dashboard.webp", alt: "Analytics dashboard showing weekly traffic", width: 1600, height: 1000 },
      { src: "/screenshots/mobile-checkout.webp", alt: "Mobile checkout form with order summary", width: 1170, height: 2532 },
      { src: "/screenshots/landing-page.jpg", alt: "Landing page with a blue call-to-action panel", width: 1440, height: 900 }
    ];

    const image = document.querySelector("#shot");
    const caption = document.querySelector("#caption");
    const status = document.querySelector("#status");
    const error = document.querySelector("#error");
    let previousIndex = -1;

    function randomIndex() {
      if (screenshots.length < 2) return 0;
      let index;
      do { index = Math.floor(Math.random() * screenshots.length); }
      while (index === previousIndex);
      return index;
    }

    function showRandomScreenshot() {
      if (screenshots.length === 0) {
        image.removeAttribute("src");
        error.hidden = false;
        error.textContent = "No screenshots are configured.";
        return;
      }
      const index = randomIndex();
      previousIndex = index;
      const shot = screenshots[index];
      error.hidden = true;
      image.alt = shot.alt;
      image.width = shot.width;
      image.height = shot.height;
      caption.textContent = shot.alt;
      status.textContent = "Loading screenshot…";
      image.onload = () => { status.textContent = "Screenshot loaded."; };
      image.onerror = () => {
        status.textContent = "";
        error.hidden = false;
        error.textContent = "This screenshot could not be loaded.";
      };
      image.src = shot.src;
    }

    document.querySelector("#another").addEventListener("click", showRandomScreenshot);
    showRandomScreenshot();
  </script>
</body>
</html>

Math.random() chooses an index from zero through the final array index. The loop avoids immediately repeating the previous item when at least two records exist. It does not guarantee that every screenshot appears once before any repeat; use a shuffled queue if you need that behavior.

Show every item once before reshuffling

For galleries, contests or presentations where repetition is undesirable, shuffle a copy of the indexes and consume it:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
let queue = [];
function refillQueue() {
  queue = screenshots.map((_, i) => i);
  for (let i = queue.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [queue[i], queue[j]] = [queue[j], queue[i]];
  }
}
function nextIndex() {
  if (queue.length === 0) refillQueue();
  return queue.pop();
}

Call nextIndex() in place of randomIndex(). A refresh or a new visitor starts a new sequence unless you persist the queue in browser storage.

Rank #2
Sale
HTML and CSS: Design and Build Websites
  • HTML CSS Design and Build Web Sites
  • Comes with secure packaging
  • It can be a gift option

Accessibility and layout stability

Write alt text that communicates the screenshot’s purpose, not its filename. If the screenshot is purely decorative, use an empty alt="" and provide the information elsewhere. Do not omit the attribute: MDN notes that alt text is also shown when an image cannot load because of network errors, content blocking or link rot.

Set accurate width and height values. The browser can reserve the correct aspect ratio before the bytes arrive, reducing layout movement. Keep CSS responsive with max-width:100% and height:auto; never use dimensions that distort the source.

If captions are useful, render them as visible text or a <figcaption>, as in the example. A button should be a real <button>, not a clickable <div>, so keyboard and assistive-technology users can operate it.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Remote images, CORS and canvas: three different cases

Direct display with img src

A remote image can generally be displayed by setting src; the browser does not expose the image’s pixels to your JavaScript merely because it is visible. This is the simplest option when your page only needs to show the screenshot.

Fetching image bytes with JavaScript

If you call fetch() on another origin to enumerate or download images, the request is subject to the same-origin policy. The remote server must send an appropriate Cross-Origin Resource Sharing (CORS) response. See MDN’s same-origin policy and CORS guide. A direct img list avoids this extra dependency when you already know the URLs.

Reading pixels or exporting a canvas

Canvas access is stricter. A cross-origin image without permission can taint the canvas, preventing pixel reads and exports. Adding crossorigin="anonymous" makes the image request a CORS request; if the server does not grant your origin, the image itself may fail to load. MDN explains this workflow in Use cross-origin images in a canvas. Configure the image host first, then use the matching crossorigin mode.

Content Security Policy for screenshot hosts

A Content-Security-Policy response header controls which resources a browser may load. MDN’s CSP reference documents that img-src limits image origins; if it is absent, default-src applies to images.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For local images, a policy might include:

Content-Security-Policy: default-src 'self'; img-src 'self'; script-src 'self'

For a known CDN, add its exact origin:

Content-Security-Policy: default-src 'self'; img-src 'self' https://cdn.example.com; script-src 'self'

Do not add a wildcard merely to make a broken request disappear. Identify the host your page actually uses. Mozilla’s Web Security Guidelines recommend CSP as a strong defense for new websites and explain that a policy disallowing unsafe inline JavaScript requires scripts to come from permitted sources. Move the example script into an external file if your policy excludes inline scripts, and attach the listener with JavaScript rather than an inline onclick attribute.

Local list, remote API or generated collection?

Approach Best for Advantages Costs and risks
Curated local assets Small, stable collections Control over availability, rights, dimensions and caching You must update the list and deploy new files
Curated remote URLs Assets hosted on a CDN or media service Smaller application bundle and centralized delivery Hotlink blocks, URL changes, outages and CORS/CSP configuration
API-backed list Large or frequently changing collections Central discovery and metadata updates Authentication, quotas, API failures, changing records and cross-origin requirements

If an API supplies records, validate that each URL uses HTTPS, belongs to an allowed host and includes usable alt text or a safe fallback. Do not let arbitrary user input become an image URL without an allowlist: an attacker could use your page to embed unwanted content or bypass your intended CSP.

Performance and reliability details

Choose appropriate files

Use WebP or AVIF when your image pipeline and browser support requirements allow it, and provide dimensions from the source metadata. Avoid shipping a multi-megapixel screenshot when the display area is small. If you need multiple sizes, use responsive image techniques such as srcset and sizes, but keep each candidate’s dimensions and alt text consistent.

Rank #4
Sale
Web Design with HTML, CSS, JavaScript and jQuery Set
  • Brand: Wiley
  • Set of 2 Volumes
  • A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers

Preload only when it helps

The initially selected image is not known until JavaScript runs, so a blanket preload can download the wrong asset. For a server-rendered first choice, preload that known URL; for a client-randomized page, let the selected image request begin and consider preloading only a small, high-probability set.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Handle failure explicitly

The error handler in the example leaves the page usable when a URL is dead or blocked. For a production page, you can remove the failed record from the in-memory list and select another, while retaining a message if every record fails. Log failures on your own server if you need operational visibility; do not expose private source URLs in client-side logs.

Cache deliberately

Local static files can use long-lived cache headers when filenames are content-hashed. Remote URLs should follow the host’s cache policy. If editors replace an image without changing its URL, visitors may continue to see an older cached copy; version the filename or query string only when your cache strategy permits it.

Troubleshooting checklist

  • Broken image icon: Open the URL directly, check its spelling and case, inspect the Network panel for a 404, and verify that the server permits image responses.
  • Works locally but not after deployment: Check whether the deployed base path changes relative URLs. Prefer root-relative or correctly resolved URLs and confirm the production host is included in CSP.
  • CORS error from fetch(): The image server has not granted your origin. Use a same-origin proxy you control, configure CORS on the source, or stop fetching bytes and use direct img src display.
  • Canvas SecurityError: The image was loaded without successful CORS permission. Configure the server’s Access-Control-Allow-Origin, set crossorigin="anonymous" before src, and reload.
  • Image blocked by CSP: Read the browser console, then add only the required origin to img-src (or correct default-src).
  • Every click looks the same: Confirm the array contains multiple records and that the button listener is attached. The no-immediate-repeat loop intentionally permits repeats after other entries have appeared.
  • Layout jumps: Store accurate intrinsic dimensions and apply height:auto. Missing or incorrect dimensions prevent the browser from reserving the right space.
  • Screen readers announce unhelpful text: Replace filenames and generic phrases with concise descriptions of what each screenshot communicates.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

For screenshots of live websites, ScreenshotNeo returns a PNG, JPEG, WebP or PDF from one request. Its capture flow accepts cookie/consent banners and removes more than 60 known consent platforms, newsletter popups and chat widgets before the shot; each step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and response headers identify the page verdict and billing status. It also offers an MCP server for Claude, Cursor and other MCP clients, with take_screenshot, get_page_info and capture_pdf tools.

Use the API URL and options documented at ScreenshotNeo’s documentation:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
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)
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}`);

ScreenshotNeo supports full-page capture with lazy images loaded, CSS-selector element capture, dark mode, 12 device presets and custom viewports, retina scale, PDF paper and page controls, custom CSS and JavaScript, clicks, selector or network-idle waits, request and resource blocking, headers, cookies, user agents, Authorization, timezone, geolocation, transparent backgrounds, resizing, chosen cache TTLs, signed image links, asynchronous webhooks, up to 100 URLs per bulk call, a usage API and an OpenAPI specification. Parameter names used by other screenshot APIs also work.

The Free plan includes 1,000 screenshots each month with no card. Paid plans start at $5 for 3,000 shots; every feature is on every plan, and yearly billing gives two months free. Sign up for the free plan to get started.

FAQ

Can I choose a screenshot server-side?

Yes. Render one record into the initial HTML or pass a selected record to the page, then keep the button logic client-side. Server-side selection can improve first paint and lets you enforce an allowlist before the browser receives a URL.

How can I make a shareable random result?

Store a seed or record identifier in the URL, such as ?shot=mobile-checkout, and resolve it against your allowlisted array. This makes refreshes and shared links deterministic instead of random on every load.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Should a screenshot be a background image?

Use an <img> when the screenshot is content that needs alt text, intrinsic dimensions or a caption. Use CSS background-image for decoration where no textual replacement is required.

Frequently Asked Questions

Can I choose a screenshot server-side?

Yes. Render one allowlisted record into the initial HTML or pass it to the page, then use client-side JavaScript for subsequent choices.

How can I make a random result shareable?

Put a record identifier or seed in the URL and resolve it against your approved screenshot list.

Should a screenshot be a background image?

Use an img element for meaningful screenshot content; reserve CSS backgrounds for decoration without an alt-text requirement.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Read next

Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Outdated Drivers Are Slowing You DownFree scan - exact matches

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.