PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteSome links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Attach a page.onResourceRequested handler and read requestData.postData. Check requestData.method first so you only process POST requests:
var page = require('webpage').create();
page.onResourceRequested = function (requestData, networkRequest) {
if (requestData.method === 'POST') {
console.log('POST to ' + requestData.url);
console.log(requestData.postData);
}
};
page.open('https://example.com');
This gives you the body text; parsing that text into fields is a separate step. Use JSON.parse for JSON, a URL-encoded form parser for application/x-www-form-urlencoded, and treat multipart bodies as a format that needs its own parser. PhantomJS is a legacy runtime, so the technique is historical rather than a recommendation for new browser automation.
Observe a page-generated POST request
onResourceRequested runs when the page requests a resource. Its first argument, commonly named requestData, contains request metadata such as the method, URL, time and headers. For a POST, the body is available as requestData.postData; this property is identified by the directly relevant PhantomJS community answer, while the official callback summary does not enumerate it. The second argument, networkRequest, is the request-control object used for operations such as aborting, changing a URL or setting headers. Read the body from requestData, not from networkRequest.
Recommended Free Tools
Minimal logger
var page = require('webpage').create();
page.onResourceRequested = function (requestData, networkRequest) {
if (requestData.method !== 'POST') {
return;
}
console.log('POST ' + requestData.url);
console.log('Body: ' + (requestData.postData || '(empty or unavailable)'));
};
page.open('https://example.com', function (status) {
console.log('Page load: ' + status);
phantom.exit();
});
The handler can see requests made by forms, XMLHttpRequests and other resources initiated while the page is loading. Register it before page.open; otherwise an early request can be missed. Filter by URL as well when a page makes many POSTs:
#1 Best Overall
page.onResourceRequested = function (requestData, networkRequest) {
if (requestData.method === 'POST' &&
requestData.url.indexOf('/api/') !== -1) {
console.log(requestData.url);
console.log(requestData.postData || '');
}
};
Parse JSON and URL-encoded form bodies
postData is request-body text, not an already populated JavaScript object. Determine the serialization used by the sender (usually its Content-Type header) before converting it.
JSON payloads
For a JSON body such as {"email":"[email protected]","roles":["admin"]}, call JSON.parse and catch errors. A malformed body, an empty body or a non-JSON POST must not terminate the request callback.
function parseJsonBody(body) {
if (!body) {
return null;
}
try {
return JSON.parse(body);
} catch (error) {
console.log('Invalid JSON: ' + error.message);
return null;
}
}
page.onResourceRequested = function (requestData, networkRequest) {
if (requestData.method !== 'POST') {
return;
}
var value = parseJsonBody(requestData.postData || '');
if (value !== null) {
console.log(JSON.stringify(value));
}
};
If the endpoint sometimes sends forms and sometimes sends JSON, inspect the request headers when available or use a conservative fallback: try JSON first, then parse URL-encoded text only when the body has the expected form shape. Do not silently label arbitrary text as JSON.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →application/x-www-form-urlencoded payloads
Form submissions commonly look like user=ada%40example.com&enabled=true. PhantomJS does not turn that string into an object for you. The following small parser handles percent encoding, plus signs used for spaces, repeated keys and fields without an equals sign:
Rank #2
function decodeFormComponent(value) {
return decodeURIComponent(value.replace(/+/g, ' '));
}
function parseFormEncoded(body) {
var result = {};
if (!body) {
return result;
}
body.split('&').forEach(function (pair) {
if (!pair) {
return;
}
var separator = pair.indexOf('=');
var rawName = separator === -1 ? pair : pair.substring(0, separator);
var rawValue = separator === -1 ? '' : pair.substring(separator + 1);
var name;
var value;
try {
name = decodeFormComponent(rawName);
value = decodeFormComponent(rawValue);
} catch (error) {
console.log('Invalid percent encoding in form body: ' + error.message);
return;
}
if (Object.prototype.hasOwnProperty.call(result, name)) {
if (!(result[name] instanceof Array)) {
result[name] = [result[name]];
}
result[name].push(value);
} else {
result[name] = value;
}
});
return result;
}
page.onResourceRequested = function (requestData, networkRequest) {
if (requestData.method !== 'POST') {
return;
}
var fields = parseFormEncoded(requestData.postData || '');
console.log(JSON.stringify(fields));
};
The parser preserves repeated field names as arrays, which is safer than discarding all but the last value. It does not infer numbers, booleans or nested objects; those conversions are application-specific.
Multipart and other encodings
The available PhantomJS references do not specify the representation of multipart request bodies. A multipart body contains boundaries and headers for each part, so do not assume that postData can be split on ampersands or parsed as JSON. Capture the raw value for diagnosis and use a multipart parser appropriate to the runtime if you need individual file and field parts. The same caution applies to custom binary or text encodings.
Capture headers and avoid leaking credentials
Request metadata includes headers, but header shapes and values can contain cookies, authorization tokens and personal data. Log only the fields needed for debugging, redact secrets and avoid writing complete production payloads to shared logs.
function redactBody(body) {
return body.replace(/(password|token|secret)=([^&]*)/gi, '$1=[redacted]');
}
page.onResourceRequested = function (requestData, networkRequest) {
if (requestData.method === 'POST') {
var body = requestData.postData || '';
console.log(requestData.url);
console.log(redactBody(body));
}
};
This example targets URL-encoded names. JSON, multipart and custom formats need format-aware redaction; a generic regular expression is not a security boundary.
Know which callback contains which data
onResourceRequested: outgoing request
Use this callback when your question is “What did the page send?” It runs as the request is made and exposes request-side metadata, including the method, URL and (for a POST) the body value used above.
onResourceReceived: response lifecycle
Use onResourceReceived when you need the server’s response metadata: HTTP status, content type, headers and the loading stage. A large resource can trigger the callback once per chunk, so do not treat every invocation as a separate response.
var page = require('webpage').create();
page.onResourceReceived = function (response) {
if (response.url.indexOf('/api/') !== -1) {
console.log(response.status + ' ' + response.url);
console.log(response.stage);
}
};
page.open('https://example.com', function (status) {
console.log('Page load result: ' + status);
phantom.exit();
});
The status passed to the page.open callback reports page-load success or failure. It is not the HTTP status code. Read the HTTP code from the response object delivered to onResourceReceived.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsSend a controlled POST with page.open
If you are creating the request rather than observing one generated by a page, use page.open with a method and body. The short form accepts a URL, operation, data and callback:
Rank #4
var page = require('webpage').create();
page.open(
'https://example.com/login',
'POST',
'user=ada%40example.com&password=example',
function (status) {
console.log('Page load result: ' + status);
phantom.exit();
}
);
For JSON, use the settings object so the body is serialized explicitly and the content type is correct:
var page = require('webpage').create();
var settings = {
operation: 'POST',
encoding: 'utf8',
headers: {
'Content-Type': 'application/json'
},
data: JSON.stringify({
some: 'data',
another: ['custom', 'data']
})
};
page.open('https://example.com/api', settings, function (status) {
console.log('Page load result: ' + status);
phantom.exit();
});
Choose the body serialization, encoding and Content-Type expected by the server. A URL-encoded string with a JSON content type, or JSON text with a form content type, can be rejected even though the network request itself is sent.
Observe and parse a POST in one complete script
This script logs the URL, attempts JSON parsing, and otherwise parses a URL-encoded body. It is intentionally conservative: it does not claim to decode multipart data.
var page = require('webpage').create();
function parseFormEncoded(body) {
var result = {};
if (!body) {
return result;
}
body.split('&').forEach(function (pair) {
if (!pair) {
return;
}
var i = pair.indexOf('=');
var key = i === -1 ? pair : pair.substring(0, i);
var value = i === -1 ? '' : pair.substring(i + 1);
key = decodeURIComponent(key.replace(/+/g, ' '));
value = decodeURIComponent(value.replace(/+/g, ' '));
if (Object.prototype.hasOwnProperty.call(result, key)) {
if (!(result[key] instanceof Array)) {
result[key] = [result[key]];
}
result[key].push(value);
} else {
result[key] = value;
}
});
return result;
}
function inspectBody(body) {
if (!body) {
return { format: 'empty', value: null };
}
try {
return { format: 'json', value: JSON.parse(body) };
} catch (ignore) {
// Continue with the form parser when the text is not JSON.
}
if (body.indexOf('=') !== -1 || body.indexOf('&') !== -1) {
try {
return { format: 'urlencoded', value: parseFormEncoded(body) };
} catch (error) {
return { format: 'unparsed', value: body, error: error.message };
}
}
return { format: 'text', value: body };
}
page.onResourceRequested = function (requestData, networkRequest) {
if (requestData.method !== 'POST') {
return;
}
var inspected = inspectBody(requestData.postData || '');
console.log('POST ' + requestData.url);
console.log(inspected.format + ': ' + JSON.stringify(inspected.value));
if (inspected.error) {
console.log('Parse error: ' + inspected.error);
}
};
page.open('https://example.com', function (status) {
console.log('Page load result: ' + status);
phantom.exit();
});
The fallback is a debugging convenience, not a content-type detector. For production tooling, use the request’s declared content type and a parser designed for that format.
Best Value
Performance, reliability and PhantomJS’s age
Keep the request hook cheap
- Filter by method and URL before parsing.
- Do not stringify or print large bodies unless a diagnostic run requires it.
- Write structured, redacted output rather than entire authenticated requests.
- Remember that response callbacks may run repeatedly for chunked resources.
Expect legacy compatibility limits
The PhantomJS project says development is suspended until further notice and identifies 2.1 as its latest stable release. Its changelog dates PhantomJS 2.1.0 to 2016-01-23. Those facts establish the project’s age, not compatibility with a particular current website, TLS configuration or JavaScript feature. A modern site may use browser behavior or transport settings that this runtime cannot reproduce. If you must keep PhantomJS for a legacy test, pin the runtime, test the target endpoint in your environment and treat failures as possible compatibility issues rather than automatically as parser bugs.
Troubleshooting checklist
| Symptom | Likely cause | Fix |
|---|---|---|
| No POST is printed | The handler was registered after navigation, the page never submitted, or the URL/method filter excludes it. | Register onResourceRequested before page.open; temporarily log every method and URL; verify that the page actually triggers the request. |
postData is empty |
The request has no body, the body is unavailable for that request type, or the page sent data another way. | Log the method, URL and headers; inspect the browser action that initiated the request; do not substitute response data for a missing request body. |
JSON.parse throws |
The payload is form-encoded, malformed, empty or another text format. | Check the declared content type, catch the exception and select the matching parser. |
| Form fields contain plus signs or percent escapes | URL-encoded data was treated as literal text. | Convert + to spaces and apply decodeURIComponent; handle malformed escapes. |
| Repeated form fields disappear | A dictionary assignment overwrote the earlier value. | Store repeated names as arrays, as in the parser above. |
| Multipart data is unreadable | Multipart boundaries and parts are not URL-encoded pairs. | Retain the raw body and use a multipart-aware parser; the reviewed PhantomJS references do not define a universal representation. |
| The page callback says success but the API failed | page.open‘s callback status is page-load status, not HTTP status. |
Inspect onResourceReceived for the response status and stage. |
| Modern pages fail before the POST | PhantomJS 2.1 is an old, suspended project and may not support the site’s current browser or TLS requirements. | Reproduce the endpoint with a maintained browser or HTTP client, or isolate the legacy page and document the compatibility boundary. |
Or skip the browser setup
If your actual goal is a clean image or PDF of a page rather than inspection of its network traffic, ScreenshotNeo provides a single screenshot request and an MCP server for AI clients. It is unrelated to parsing PhantomJS POST bodies, but it avoids maintaining a browser process for capture work.
See the ScreenshotNeo API documentation for parameters. A minimal cURL request is:
Free tools Windows power users keep installed
One-click scans. No signup required.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
The same request 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)
And 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}`);
- Cookie and consent banners, newsletter popups and chat widgets are removed before the shot; each cleanup step can be turned off.
- Bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed as clean shots, and response headers identify the page verdict and billing result.
- The MCP server exposes
take_screenshot,get_page_infoandcapture_pdffor Claude, Cursor and other MCP clients. - The Free plan includes 1,000 screenshots per month without a card; paid plans start at $5 for 3,000 shots. Every feature is available on every plan.
Create a free ScreenshotNeo account to start with the 1,000-shot monthly allowance and no card.
Frequently Asked Questions
Does requestData.postData return a JavaScript object?
No. It is the request-body value. Decode or parse it according to the payload format, such as JSON or URL-encoded form data.
Can I use onResourceReceived to read the outgoing POST body?
No. That callback is for response metadata and lifecycle events. Use onResourceRequested for the outgoing body and onResourceReceived for the server response.
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.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.

