Free tools Windows power users keep installed
One-click scans. No signup required.
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.
#1 Best Overall
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:
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →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
- 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.
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.
Rank #3
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.
Recommended Free Tools
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
- 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.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →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 directimg srcdisplay. - Canvas
SecurityError: The image was loaded without successful CORS permission. Configure the server’sAccess-Control-Allow-Origin, setcrossorigin="anonymous"beforesrc, and reload. - Image blocked by CSP: Read the browser console, then add only the required origin to
img-src(or correctdefault-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.
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:
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Clear out junk files and repair common Windows errors3Fix the driver behind crashes, sound loss and screen glitchescurl -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.
Best Value
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.
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.
Quick Recap
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.




