ScreenshotNeo

BlogHow-to

How to Render a Local HTML File as an Image with PhantomJS

Render a local HTML file with PhantomJS using a file URL, check the load status, and control the screenshot’s format, viewport, and captured area.

By the ScreenshotNeo team4 October 20266 min read

To render a local HTML file with PhantomJS, pass its absolute path as a file:/// URL to page.open(), check the callback status, then call page.render() with an output filename whose extension selects the format. Save the script below as render.js and run phantomjs render.js.

var page = require('webpage').create();
var input = 'file:///absolute/path/to/page.html';
var output = '/absolute/path/to/page.png';

page.open(input, function (status) {
  if (status === 'success') {
    page.render(output);
  } else {
    console.log('Could not open ' + input);
  }
  phantom.exit();
});

Replace both paths with paths valid on the machine running PhantomJS. The input should be an absolute local path represented as a file URL. The output can be PNG, JPEG, BMP, PPM, or PDF; GIF support depends on the Qt build. See the official PhantomJS command-line options, page.open(), and page.render() references.

1. Prepare the file URL and run the script

  1. Install or locate the PhantomJS executable in your environment.
  2. Use an absolute path to your HTML file. For example, /home/alex/report.html becomes file:///home/alex/report.html.
  3. Save the JavaScript snippet as render.js, updating the input and output paths.
  4. Run phantomjs render.js from a shell where the PhantomJS executable is available.
  5. Confirm that the output file exists and inspect its dimensions and appearance.

The CLI syntax is phantomjs [options] somescript.js [arg1 ...]. page.open() reports success or fail in its callback. Only render after a successful open; otherwise, you risk mistaking a missing or invalid page for a valid capture. The callback should call phantom.exit() so the process terminates; the Quick Start warns that it will otherwise keep running.

PhantomJS documents local URL access as enabled by default through --local-url-access. If you need to check the setting explicitly, consult the CLI documentation. Local content accessing remote URLs is controlled separately by --local-to-remote-url-access, which defaults to false. Enable security-related access only when the document’s dependencies require it and you understand what local content will be allowed to reach.

2. Set the output format and capture dimensions

Choose a format by filename extension

page.render(filename) infers the output format from the filename extension. Use .png for lossless image output, .jpg or .jpeg for JPEG, or another supported extension such as .bmp, .ppm, or .pdf. GIF availability depends on the Qt build used by PhantomJS. A PDF output is a document capture rather than a raster screenshot.

JPEG quality is configurable from 0 to 100 and defaults to 75. For PNG, the quality setting controls lossless Deflate compression; it does not reduce visual fidelity. Refer to the official render API for the exact options exposed by your version.

Control the viewport and crop

Set page.viewportSize before opening or rendering when you need a particular browser viewport. To capture a defined rectangle, set page.clipRect with top, left, width, and height. These properties control the rendered area; choose them deliberately and verify the resulting file dimensions in your own workflow.

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

page.open('file:///absolute/path/to/page.html', function (status) {
  if (status === 'success') {
    page.render('/absolute/path/to/viewport.png');
  } else {
    console.log('Could not open the HTML file');
  }
  phantom.exit();
});

The screen capture guide demonstrates viewport and clipping configuration. A viewport-sized capture and a full-page capture are different requirements: clipping defines the rectangle to render, so do not assume it automatically measures or includes all page content.

3. Handle local assets and paths

A local HTML page may refer to images, stylesheets, fonts, or scripts. Their relative paths are resolved in relation to the document location, so keep the directory structure intact or update the references before capture. The file URL grants access to the local document, but does not guarantee that every dependency will load: verify the resulting output when assets are missing.

Paths containing spaces or URL-significant characters may need URL encoding. The reviewed PhantomJS documentation does not provide a dedicated path-to-file-URL conversion recipe. If opening fails, inspect the constructed URL and encode path characters as needed. For remote dependencies referenced by local content, check the separate --local-to-remote-url-access setting and its default of false before changing it.

4. Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. For a local HTML file, first make the page reachable at a URL the API can access; the endpoint accepts a URL, so a machine-only file:/// path is not a substitute for a reachable page.

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

Replace the example target with the reachable page URL. The same request can be made in 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)

Or in 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}`);

See the ScreenshotNeo API documentation for request options. Cookie banners, newsletter popups, and chat widgets are removed before capture. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed; response headers identify the page verdict and billing status. An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents. The free plan includes 1,000 screenshots per month with no card, and paid plans start at $5 for 3,000 shots. Sign up free for 1,000 screenshots a month, with no card required.

5. Troubleshooting

Symptom Likely cause What to check
page.open() returns fail The file URL is malformed, the file path is wrong, or the process cannot access the file. Confirm the absolute path exists, check the file:/// prefix and URL encoding, and verify filesystem permissions.
PhantomJS does not exit The callback did not reach phantom.exit(), or the script exits through another path first. Call phantom.exit() in both success and failure cases, as in the examples.
The image exists but is blank or incomplete The page did not open successfully, or referenced assets did not load. Check the open status, inspect local asset paths and the output, and confirm any remote access requirement.
Local page cannot load remote assets --local-to-remote-url-access defaults to false. Review whether remote access is necessary, then consult the CLI documentation before changing the setting.
Output format is unexpected The filename extension selects the format, or the requested format is unavailable in the build. Use a supported extension and account for GIF’s Qt-build dependency.
Capture has the wrong dimensions Viewport and clip rectangle do not match the desired region. Set page.viewportSize and page.clipRect explicitly, then inspect the generated dimensions.

6. Reliability, performance, and maintenance

PhantomJS is legacy software. In the project owner’s 2018 notice, Ariya Hidayat wrote: “PhantomJS version 2.1.1 will remain the last known stable release until further notice.” The GitHub repository is archived and read-only, with an archive date of May 30, 2023. That status matters when choosing a renderer for new projects or pages that depend on current browser behavior. See the project status notice and the archived repository.

There are no benchmark figures in the available sources, so capture speed and memory use should be measured on your own pages and environment. For repeatable output, keep input assets available, set viewport and clipping explicitly, check the open status, and verify the result file. If browser compatibility is important, evaluate a maintained browser automation option against representative pages before migrating.

Puppeteer’s Page API documents screenshot capture and setContent() for supplying HTML. It is an alternative to evaluate, not a proven drop-in replacement for every PhantomJS local-file workflow. Compare how your page is supplied, screenshot dimensions and full-page behavior, output needs, setup, and the changes required to your existing scripts. See the Puppeteer Page API.

7. Frequently asked questions

Can I render HTML without starting a web server?

Yes. Open the local document through a file:/// URL. PhantomJS documents local URL access as enabled by default.

Can PhantomJS save a PDF instead of an image?

Yes. Use a filename ending in .pdf; the render format follows the extension.

Does this recipe capture the entire page?

It sets a viewport or a clipping rectangle. Those settings define the rendered area; confirm the output dimensions and whether the content you need is inside that region.

Is PhantomJS a good choice for a new screenshot workflow?

Its repository is archived and 2.1.1 was identified by the project owner as the last known stable release. Evaluate a maintained option if current browser compatibility matters.