Recommended Free Tools
Listen for the page’s console event before the navigation or interaction that should produce the message. Filter the resulting ConsoleMessage by type or text, then await page.screenshot() when it matches. Keep the browser open until that capture finishes, and put a timeout around the wait so a message that never arrives does not leave your script hanging.
Listen before the event you want to catch
Puppeteer pages emit a console event when the page writes a console message. Its argument is a ConsoleMessage; use msg.text() to inspect the message and msg.type() to inspect its category. A listener only sees events emitted after it is registered, so install it before the relevant navigation, click, or script execution.
This example waits for an error whose text contains a target phrase, then saves the screenshot as after-console.png. Replace the URL and phrase with the page and message you expect. It uses an ES module import; in a Node.js project configured for ES modules, save it as .mjs or use a package configuration that enables import.
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
const screenshotAfterMessage = new Promise((resolve, reject) => {
const timeout = setTimeout(() => {
reject(new Error('Timed out waiting for console message'));
}, 10_000);
page.on('console', async msg => {
if (msg.type() !== 'error' || !msg.text().includes('target phrase')) return;
clearTimeout(timeout);
try {
const image = await page.screenshot({ path: 'after-console.png' });
resolve(image);
} catch (error) {
reject(error);
}
});
});
await page.goto('https://example.com');
// Or perform the interaction expected to emit the target message here.
await screenshotAfterMessage;
} finally {
await browser.close();
}
The timeout is a practical guard, not a special Puppeteer console-wait method. Without a matching message the promise rejects after ten seconds; with a match it resolves after the screenshot operation succeeds. The finally block closes the browser whether navigation, waiting, or capturing fails.
#1 Best Overall
- HTML CSS Design and Build Web Sites
- Comes with secure packaging
- It can be a gift option
Choose the message that should trigger the capture
Match by type
msg.type() distinguishes categories such as error, warn, log, and info. The example requires error, so an ordinary log containing the same phrase will not trigger it. To capture any error regardless of its text, remove the text condition:
if (msg.type() !== 'error') return;
Match by text
msg.text() returns the message text. The example uses includes(), which matches a phrase anywhere in the message and is usually more robust than comparing the entire string when the page adds variable details. For an exact match, use msg.text() !== 'Expected message' instead. If the site varies capitalization, normalize the text before matching, for example with msg.text().toLowerCase().includes('target phrase').
Combine conditions deliberately
Using both a type and a text test narrows the trigger: the screenshot is taken only when both conditions match. If you only care that a particular phrase appeared, regardless of whether the page emitted it as a warning or log, remove the type test. Be explicit about this choice; otherwise a script can wait until timeout even though the phrase appeared under a different message type.
Rank #2
- 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
Handle one message or recurring messages
page.on('console', handler) leaves the handler registered for subsequent events. That is appropriate when the page may log several messages before the target appears, but it also means further matching messages can arrive while a screenshot is being taken. The sample clears its timer on the first match but does not unregister the listener. For a one-shot capture, guard the handler so later matches do not start additional screenshots:
let captured = false;
page.on('console', async msg => {
if (captured || msg.type() !== 'error' || !msg.text().includes('target phrase')) return;
captured = true;
// Take and handle the screenshot here.
});
Alternatively, use page.once('console', handler) if the very next console event is necessarily the one you want. That is not suitable when unrelated console messages may occur first: once consumes the first event whether or not it matches. For repeated captures, serialize the screenshot work or otherwise coordinate it; launching captures concurrently in response to rapid matching messages can produce overlapping work and makes it less clear which event each image represents.
Decide what part of the page to capture
With page.screenshot({ path: 'after-console.png' }), Puppeteer captures the current viewport by default. Select the capture scope according to what the console event is meant to document.
Rank #3
- Viewport: omit extra options when the visible screen is the evidence you need.
- Entire page: pass
fullPage: trueto capture the full page rather than only the viewport. - Region: pass a
cliprectangle when only a particular portion of the page matters. - One element: locate the element and use its
ElementHandle.screenshot()method. Puppeteer scrolls that element into view if needed.
The message is a trigger, not a guarantee that the page is visually ready. A console error can occur before an image, animation, or later layout update completes. If the screenshot must show a particular state, wait for the relevant page condition as well as the console message, or capture an element whose presence indicates that state. The right condition is page-specific; do not assume that every console event means rendering has finished.
Control the output file and format
The path option determines where the screenshot is saved, relative to the script’s working directory unless you provide an absolute path. Puppeteer infers the output image type from the filename extension; with no other type specified, the screenshot defaults to PNG. The example writes after-console.png. Choose a supported extension matching the format you want and ensure the process can write to that directory.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errorsIf you need the image in memory rather than saved directly to disk, await page.screenshot() without a path and use the returned image data. In the sample, the screenshot result is passed to resolve; the script only waits for completion and does not otherwise use that returned value. Saving to a path is simpler for a local debugging artifact, while an in-memory result is useful when the next step in your own program consumes the image.
Rank #4
Install and run the Puppeteer script
The code requires Node.js and the Puppeteer package in the project. Install the package using your project’s normal package manager, then run the script in the module format it uses. Puppeteer manages a browser for page navigation and screenshots; ensure the runtime environment permits that browser to launch and that the target URL is reachable from it.
- Create a project or use an existing Node.js project, and install
puppeteerusing your package manager. - Save the example as an ES module file, such as
capture.mjs, or adapt the import to your project’s module setup. - Replace
https://example.comandtarget phrasewith the URL and expected console text, and change the match conditions if needed. - Run the file with Node.js. On a successful match, look for
after-console.pngin the process working directory. - If no matching message occurs before the timeout, check the page behavior and filter conditions rather than increasing the timeout blindly.
Troubleshoot missed messages and failed captures
The script times out although the page logs something
- Listener registered too late: create the promise and attach
page.on('console', ...)beforepage.goto()or the action that emits the message. - Filter too narrow: temporarily inspect
msg.type()andmsg.text()for incoming messages, then adjust exact versus substring matching and the expected type. - Wrong trigger action: navigation may not produce the target message; if a click or script produces it, perform that action after installing the listener.
- Message belongs to another page or context: attach the listener to the Puppeteer
Pagethat actually produces the message.
The screenshot is missing or the script exits early
- Browser closes before capture completes: await the screenshot promise before leaving the
tryblock. Keep cleanup infinally, after the awaited work. - Capture throws: the example rejects the promise if
page.screenshot()fails. Check the error and verify that the output directory exists and is writable. - Unexpected output location: a relative
pathis interpreted from the process working directory, which may differ from the script’s folder. Use an absolute path if necessary. - Image shows an earlier or incomplete state: a console message alone does not prove that subsequent visual changes have completed. Wait for a page-specific selector or state before capturing.
Several images are produced for one expected event
A persistent on listener handles every matching event. Add a first-match guard, unregister the handler after the first accepted message, or choose once only when the first event itself is guaranteed to be the intended trigger. Do not run overlapping screenshot operations unless concurrent captures are genuinely wanted.
Performance, reliability, and cost considerations
This approach launches a browser, navigates or interacts with a page, waits for an event, and captures an image. Its completion time therefore depends on the page, the action, the message and the screenshot operation; no fixed performance or reliability figure follows from the Puppeteer API. Keep the timeout aligned with the expected behavior and fail clearly when the trigger never appears. For repeated automated runs, make sure each run closes the browser and that event handlers cannot accumulate across reused pages.
Best Value
- JavaScript Jquery
- Introduces core programming concepts in JavaScript and jQuery
- Uses clear descriptions, inspiring examples, and easy-to-follow diagrams
For debugging, consider capturing the smallest useful scope: a viewport is generally simpler than a full-page capture, while an element capture can focus the artifact. Full-page images may be more useful for long documents but can create larger artifacts. Puppeteer itself does not impose a per-screenshot price in this example; runtime and infrastructure costs depend on where and how you run the browser.
Or skip the browser setup
If you need a screenshot of a URL rather than a screenshot triggered by a particular browser console event, ScreenshotNeo provides a one-request screenshot API. It is not a drop-in replacement for Puppeteer’s event listener: use Puppeteer when a specific console message must trigger the capture.
Install the Python requests package to run this Python example. Replace the URL as needed and supply your API key:
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://example.com"},
timeout=90,
)
open("shot.webp", "wb").write(r.content)
See the ScreenshotNeo API documentation for request options. Cookie banners, newsletter popups and chat widgets are removed before the shot; bot checks, blank pages and failed loads are never billed. Its MCP server lets AI agents take screenshots, and 1,000 screenshots per month are free with no card; paid plans start at $5 for 3,000. Sign up for free and get 1,000 screenshots a month with no card.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Frequently Asked Questions
Does Puppeteer provide a built-in wait-for-console-message method?
The documented pattern here uses the page’s console event and a JavaScript promise; the timeout is application logic rather than a dedicated console-wait API.
Can I trigger a capture on a console warning instead of an error?
Yes. Change the type comparison from error to warn, or omit type filtering if the message text alone identifies the trigger.
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.




