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

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Create the page in PhantomJS, add your badge or watermark with page.evaluate(), wait for any overlay assets to load, then set the crop and scale before rendering. PhantomJS development is suspended, so this is best treated as a legacy workflow rather than a foundation for a new screenshot service.

What the workflow does

PhantomJS renders a web page through its webpage module. To make a thumbnail with an overlay, open the page, add the overlay to the loaded document, and render the result after the relevant content is ready. Keeping the overlay in the same document means the page and overlay are painted in the same render pass.

The key geometry settings have different jobs: viewportSize controls the dimensions used for page layout, clipRect selects the captured rectangle, and zoomFactor scales the rendering. Choose them deliberately; changing one is not a substitute for configuring the others.

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

Build and run a basic overlay thumbnail

Save this as thumbnail.js and run it with an installed PhantomJS executable, for example phantomjs thumbnail.js. Change the source URL and output path to suit your use.

var page = require('webpage').create();
page.viewportSize = { width: 1280, height: 720 };
page.clipRect = { top: 0, left: 0, width: 1280, height: 720 };

page.open('https://example.com/', function (status) {
  if (status !== 'success') {
    console.log('Unable to load page');
    phantom.exit(1);
    return;
  }

  page.evaluate(function () {
    var badge = document.createElement('div');
    badge.textContent = 'PREVIEW';
    badge.style.position = 'fixed';
    badge.style.right = '24px';
    badge.style.bottom = '24px';
    badge.style.padding = '8px 12px';
    badge.style.background = 'rgba(0,0,0,.72)';
    badge.style.color = '#fff';
    badge.style.font = 'bold 20px sans-serif';
    badge.style.zIndex = '2147483647';
    document.body.appendChild(badge);
  });

  page.zoomFactor = 0.5;
  page.render('thumbnail.png');
  phantom.exit();
});

The viewport and clip rectangle here are 1280 by 720 CSS pixels, while the zoom factor is set to 0.5. Treat those as example settings, not universal thumbnail dimensions or a quality recommendation. The PhantomJS screen-capture example documents viewport, clipping, zoom, and rendering controls: PhantomJS screen capture documentation.

page.evaluate() runs the supplied function in the page context. It can exchange JSON-serializable arguments and results with the outer script; it cannot return a DOM node as a usable object. Here, the function creates and styles the badge directly in the document. See the page.evaluate API.

Place different kinds of overlays

Text badge or watermark

A div is suitable for a short label or text watermark. Change textContent, positioning, padding, color, and font styling to fit the design. Use position: fixed when the badge should be anchored to the visible viewport, or position: absolute when it should be positioned relative to the document. Fixed placement may behave differently on pages with transforms or complex stacking contexts, so inspect the rendered result.

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

Image logo or watermark

Create an img element in the page context, set its source and dimensions, and append it to the document. Do not render until the image has loaded; otherwise the thumbnail can contain an empty space where the logo belongs. For an external asset, verify that the page can reach its URL. For a local asset, serve it over HTTP or embed it as a data URL rather than assuming a file: URL will be available under every security configuration.

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

SVG or canvas graphic

An SVG element works well for crisp vector marks and simple shapes. A canvas is useful when the overlay is drawn programmatically. In either case, create it inside the document and ensure the drawing or asset-loading step has completed before rendering.

Wait for content and overlay assets

page.open() reporting success does not establish that every image, web font, or asynchronously generated page element needed for the final composition is ready. PhantomJS does not provide one universal asset-ready event for every page. Implement a readiness condition that matches the page you are capturing.

  • For an overlay image, attach an onload handler and signal the outer script when it fires; handle load errors as well.
  • For a known page element, poll for its presence or for a page-specific ready flag before rendering.
  • For a set of images, inspect document.images and wait until the relevant images are complete. Account for broken images so polling does not continue indefinitely.
  • For web fonts or content loaded asynchronously, use a page-specific signal or a measured delay appropriate to that site. A fixed delay is simple but can be either wasteful or too short, depending on network and page behavior.

Keep all waits bounded with a timeout and exit with a failure status if readiness never arrives. That prevents a stalled page from leaving a worker process running indefinitely. The documented mechanisms for page-context execution and loading helper scripts are described in the evaluate API, injectJs API, and includeJs API.

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

Control crop, scale, and output format

Set the layout viewport

Set page.viewportSize before opening the page when you want it to lay out for a known browser viewport. A 1280 by 720 viewport, for example, requests a widescreen layout, but responsive sites may choose different content at other dimensions. Use the viewport that matches the design you intend to capture.

Crop with clipRect

Set page.clipRect to capture only a region, using top, left, width, and height. The rectangle should match the target crop in the page’s rendered coordinate space. A clip does not redesign or reflow the page; adjust the viewport when you need different responsive layout, and adjust the clip when you need a different captured region.

Scale with zoomFactor

page.zoomFactor scales the rendered page. The API documentation gives 0.25 as an example for a thumbnail preview; it is an example configuration, not a measured performance result or universal setting. Test the final pixel dimensions and legibility, especially for text overlays.

Choose an output format

PhantomJS documents PNG, JPEG, GIF, and PDF output through its rendering API. For example, a JPEG can specify format and quality:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
page.render('thumbnail.jpg', { format: 'jpg', quality: 90 });

That quality value is a setting example, not a blanket recommendation. Compare format choices against your actual needs: PNG is lossless but can produce larger files; JPEG can reduce file size for photographic content but introduces compression; GIF is useful for its supported image characteristics rather than as a default thumbnail format. Decide based on output dimensions, text clarity, visual artifacts, and file size. The render API documents the method and options, while the screen capture example shows capture controls.

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

Create a controlled composition from local HTML

If the thumbnail should not depend on a live page’s layout, create a self-contained HTML string containing the source image, text, and overlay. Load it with page.setContent(html, baseUrl), then render after its assets are ready. setContent changes the page content and URL without making an HTTP request. For relative asset URLs, provide an appropriate base URL; remote assets still need to be reachable. See the setContent API.

For local image files, a small local HTTP server or a data URL is more predictable than relying on file: access. Check the security configuration in the environment where PhantomJS runs, particularly if captures happen in a worker or container.

Make the capture more reliable

  • Check page status. Stop when page.open() does not report success rather than saving a misleading thumbnail.
  • Wait for the actual capture condition. A successful navigation is not proof that images, fonts, overlays, or JavaScript-generated content are ready.
  • Keep overlays in the page document. This lets PhantomJS paint the overlay alongside the page in one render pass.
  • Inspect stacking and positioning. A high z-index helps, but stacking contexts, transforms, and page styles can still affect which elements appear on top and where fixed elements land.
  • Account for remote-page behavior. Redirects, authentication requirements, cross-origin restrictions, and asynchronous content can all affect the final capture.
  • Exit on every path. Call phantom.exit() after success and failure paths so the process terminates. If using asynchronous asset waits, only render and exit after readiness or timeout has been resolved.

Troubleshooting common thumbnail failures

Symptom Likely cause What to check or change
No image or a failed capture The page did not open successfully, or it redirected to a page that cannot be captured as expected. Check the status passed to the page.open() callback, confirm the URL is reachable from the PhantomJS host, and handle authentication or redirects explicitly.
Badge or logo is missing The overlay was not appended, its asset has not loaded, or another stacking context obscures it. Verify the element exists after page.evaluate(), wait for image loading, and inspect positioning, transforms, and stacking contexts.
Logo appears blank Rendering began before the image loaded, or its URL is inaccessible. Use an image-load readiness signal; verify external reachability or serve a local asset over HTTP/embed it as a data URL.
Wrong crop or dimensions The viewport, clip rectangle, and zoom factor do not correspond to the intended final geometry. Set the intended layout viewport, check clip rectangle coordinates and dimensions, then verify the rendered output dimensions and content placement.
Text is too small or blurry The layout was scaled down or the chosen format and compression obscure fine details. Try a larger viewport or a different zoom factor, tune overlay font size for final pixels, and compare PNG with JPEG output.
Thumbnail omits content loaded by JavaScript The render occurred before the page-specific content was inserted. Wait for a selector or application readiness signal rather than assuming navigation completion means the page is fully rendered.
Process hangs An asynchronous readiness condition never resolves, or an exit path was missed. Add a bounded timeout, handle asset failures, and call phantom.exit() from both success and failure paths.
Local asset is blocked The runtime’s security policy does not permit the expected file: access. Serve the asset locally over HTTP or embed it as a data URL; do not rely on file access being universally permitted.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Using PhantomJS in a new or existing system

The PhantomJS homepage states, “Important: PhantomJS development is suspended until further notice.” See the PhantomJS homepage. That makes this approach most appropriate for maintaining a legacy capture job where its behavior is already understood. For a new production system, evaluate a maintained headless browser or a hosted renderer against browser compatibility, CSS and font fidelity, sandboxing, operational cost, and API stability. PhantomJsCloud documents hosted JPEG/PNG previews and thumbnail rendering as one option: PhantomJsCloud.

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

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. It accepts a URL in one GET request and can return PNG, JPEG, WebP, or PDF. To capture a URL, use this cURL example; create an API key in your account and replace the placeholder:

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

See the ScreenshotNeo API documentation for request options. The same request in Python and Node.js:

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)
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 accepts consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be disabled. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. Try ScreenshotNeo at screenshotneo.com, or sign up for 1,000 free screenshots a month with no card.

Frequently Asked Questions

Can PhantomJS render an overlay as part of the screenshot?

Yes. Add it to the loaded document with `page.evaluate()` before calling `page.render()`.

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

Does PhantomJS have one universal event that means every asset is ready?

No. The readiness check must reflect the page and overlay assets you need to capture.

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.