ScreenshotNeo

BlogHow-to

How to Set Custom Headers and Cookies in PhantomJS Before a Screenshot

Set PhantomJS headers and cookies before navigation, verify the load, then render. Includes header scope, cookie rules, errors, and a ScreenshotNeo option.

By the ScreenshotNeo team4 October 20267 min read

Set page.customHeaders and add cookies with page.addCookie() before calling page.open(). Set the User-Agent through page.settings.userAgent. In the open callback, render only when the status is success. PhantomJS applies custom headers to page and resource requests by default, so clear them in onInitialized if they should be sent only on the initial navigation.

This guide is for maintaining existing PhantomJS automation. Its API documentation is legacy documentation; verify behavior in the PhantomJS version and environment you maintain, especially with current sites and their TLS or server policies.

1. Complete PhantomJS example

Save this as capture.js, then run it with your installed PhantomJS executable as phantomjs capture.js. Replace the example URL, header, and cookie values. The script checks cookie insertion and navigation status before saving the image.

var page = require('webpage').create();
var targetUrl = 'https://example.com/';

// Configure the User-Agent separately from ordinary custom headers.
page.settings.userAgent = 'ExampleUserAgent';

// By default these headers are sent with page and resource requests.
page.customHeaders = {
  'X-Example': 'value',
  'DNT': '1'
};

var cookieAdded = page.addCookie({
  name: 'session',
  value: 'example-value',
  domain: 'example.com',
  path: '/',
  httponly: true,
  secure: true
});

if (!cookieAdded) {
  console.log('Cookie was not added; check its domain and fields.');
}

page.open(targetUrl, function (status) {
  if (status !== 'success') {
    console.log('Navigation failed with status: ' + status);
    phantom.exit(1);
    return;
  }

  page.render('screenshot.png');
  console.log('Saved screenshot.png');
  phantom.exit();
});

The cookie domain must match the target page’s domain. A successful addCookie return value means PhantomJS accepted the cookie; it does not guarantee that the website will honor it or that the session is valid. This example follows the documented API sequence and is not a claim of tested compatibility with every site. See the customHeaders documentation, addCookie documentation, and page automation guide.

2. Configure the request context

Custom headers

Assign an object to page.customHeaders before page.open():

page.customHeaders = {
  'X-Example': 'value',
  'DNT': '1'
};

By default the headers are sent for every request issued by the page, including resource requests such as scripts and images. Header names and values are encoded as US-ASCII. Avoid assuming arbitrary Unicode header values will be preserved. The PhantomJS customHeaders reference documents the scope and encoding.

User-Agent

Set the User-Agent using page.settings.userAgent:

page.settings.userAgent = 'ExampleUserAgent';

Although page.customHeaders can overwrite the configured User-Agent, the documented setting for it is page.settings.userAgent. Use that property to make your intent clear. See the customHeaders reference.

Cookies

Use page.addCookie(cookieObject) before navigation when the goal is to add a cookie. Typical fields are name, value, domain, and path; httponly, secure, and expires are optional. Check the method’s boolean return value. A cookie with a domain that does not match the target page may be rejected or ignored. See addCookie.

var added = page.addCookie({
  name: 'session',
  value: 'example-value',
  domain: 'example.com',
  path: '/',
  secure: true,
  httponly: true
});

page.cookies exposes cookies visible to the current URL and may include cookies already in PhantomJS’s CookieJar. It is useful for inspecting visible cookies, while addCookie is the preferred method for adding one. See the cookies reference.

3. Choose the right header scope

Need Approach Tradeoff
Send common headers across the page and its resources Set page.customHeaders before opening Headers apply to every request issued by the page by default.
Send custom headers only on the initial navigation Set them before opening, then clear them in onInitialized Validate the request flow for your page and PhantomJS version.
Set a header for a particular request Use onResourceRequested and networkRequest.setHeader() This provides request-level control; the documentation does not establish all site-specific precedence behavior.

Initial navigation only

The documented workaround is to clear the header object when the page initializes. Install the handler before calling page.open():

page.customHeaders = { 'X-Example': 'value' };
page.onInitialized = function () {
  page.customHeaders = {};
};

Confirm which requests receive the header in your own setup. This narrows the intended scope; site redirects and resource-loading behavior still need to be checked in the environment you maintain. See the documented workaround.

Per-resource request hook

For request-level handling, PhantomJS provides page.onResourceRequested(requestData, networkRequest). The request object exposes setHeader(key, value):

page.onResourceRequested = function (requestData, networkRequest) {
  // Inspect requestData and apply a header when appropriate.
  // Example: networkRequest.setHeader('X-Example', 'value');
};

This snippet shows the documented hook shape; decide which request types or URLs need the header and validate the resulting requests. The API reference documents the handler and setHeader, but not every precedence or site-specific detail. See onResourceRequested.

4. Wait for the right point to capture

page.open‘s callback reports whether navigation succeeded. Call page.render() after a successful load, as in the complete example. For sites that populate content after the initial load, a successful navigation alone may not mean the desired content is ready. Add a page-specific readiness check or delay only when needed, and determine what condition indicates completion for that site. The PhantomJS automation guide documents rendering and page.clipRect, which selects the screen area to capture: Page Automation with PhantomJS.

For a clipped screenshot, set page.clipRect before rendering:

page.clipRect = { top: 0, left: 0, width: 1280, height: 800 };
page.render('screenshot.png');

Use a rectangle suited to your target viewport and page. A clip rectangle controls the captured area; it does not itself ensure that late-loading content has finished.

5. Troubleshooting

Symptom Likely cause Fix
addCookie returns false or the site appears logged out The cookie domain does not match the target, required fields are missing, or the site does not accept the cookie/session. Check the cookie domain, path, and fields; check the return value and inspect cookies visible to the URL. Validate the site’s session rules separately.
A custom header appears on image or script requests too This is the default scope of page.customHeaders. Clear the headers from onInitialized after setting them for the initial navigation, or use the resource hook when request-level decisions are needed.
The User-Agent did not change as expected It was configured as an ordinary custom header or another header assignment overwrote it. Set page.settings.userAgent before navigation and review the custom header object.
Navigation status is not success The page did not load successfully in the maintained PhantomJS environment. Do not render as if navigation succeeded. Log the status, check the URL and environment, and verify whether the site is compatible with that PhantomJS version.
Screenshot is blank or misses content that appears later Rendering happened before the needed content became available, or the clip rectangle excludes it. Capture only after the page-specific readiness condition; inspect and adjust clipRect if using one.
Non-ASCII header data is corrupted or rejected The API documents header names and values as US-ASCII. Use ASCII header values or encode application data according to the receiving server’s expected protocol.
A header works on one request but not another Header scope, hook timing, request type, or server behavior differs across the request flow. Inspect the requests in the maintained environment and choose global custom headers, the initial-navigation workaround, or the request hook based on the intended scope.

6. Reliability, performance, and cost

PhantomJS documents the relevant methods, but the sources do not establish compatibility with current websites, current TLS behavior, or particular server policies. Treat screenshot correctness as dependent on your PhantomJS version, target site, and the moment at which you render. Check both the cookie insertion result and navigation status, and avoid reporting a screenshot as successful if the load failed.

Capture performance depends on the page and its resources; the cited documentation provides no benchmark. Keep waits tied to actual page requirements, since unnecessary waiting adds time to each capture. A clip rectangle can limit the captured area, but does not replace a readiness check.

The PhantomJS sources provide no service pricing or per-capture cost figures. For a maintained automation pipeline, account for the cost of operating its runtime and investigating failures; do not infer cost or reliability from API documentation alone.

7. Or skip the browser setup

If you need screenshots through an API instead of maintaining a PhantomJS page, ScreenshotNeo accepts one GET request with a URL and returns a PNG, JPEG, WebP, or PDF. See the ScreenshotNeo API documentation. For example, this cURL request saves a WebP screenshot:

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}`);
const bytes = new Uint8Array(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', bytes));

ScreenshotNeo removes cookie banners, popups, and chat widgets before the shot. Bot checks, blank pages, and failed loads are never billed; the response indicates the page verdict and billing status. Its MCP server lets AI agents take screenshots. The Free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Sign up for 1,000 free screenshots a month, with no card.

8. FAQ

page.cookies can expose cookies visible to the current URL, including cookies already in the CookieJar. Use page.addCookie() when you need to add one.

No. It confirms PhantomJS accepted the cookie object, not that the server accepted the session or granted access.

Can I use the same custom headers for every request?

Yes. That is the default behavior of page.customHeaders for page and resource requests. Clear the object at initialization when only the initial navigation should carry it.

Does this establish that PhantomJS works with modern sites?

No. The cited pages describe the API, not compatibility with current sites, TLS implementations, or server policies. Validate the target in the PhantomJS environment you maintain.