Use Playwright’s response waiter when one user action should produce one XHR; use a response listener for a stream of requests. In SeleniumBase, the documented approach is CDP Mode: listen for Network.ResponseReceived, retain XHR request IDs, and call Network.getResponseBody for each ID. Register any waiter or handler before navigation or the click that triggers traffic. That ordering prevents the most common race.
Choose the capture pattern first
| Need | Playwright | SeleniumBase |
|---|---|---|
| One response caused by one action | expect_response() (Python) or waitForResponse() (JavaScript) |
Install a CDP response handler, then correlate the request ID |
| Observe many requests | page.on("response", handler) |
Collect Network.ResponseReceived events whose type is XHR |
| Read the body | Use the returned Response body API after it is available |
Call CDP Network.getResponseBody(request_id); retain its base64 flag |
The sources document the APIs and event order, but do not establish that either tool is universally faster or more reliable. Browser version, site behavior and your predicate determine results.
Playwright: capture one XHR caused by an action
Python synchronous API
Enter the response context before clicking. The context records the matching response while the action runs.
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.goto("https://example.com")
with page.expect_response(
lambda response: "/api/items" in response.url
and response.request.method == "GET"
) as response_info:
page.get_by_role("button", name="Load items").click()
response = response_info.value
print("status:", response.status)
print("url:", response.url)
print("body:", response.text())
browser.close()
The predicate can inspect URL, method, status or other response properties. If a glob is used instead, Playwright matches the entire URL; a regular expression or predicate is often clearer when query strings vary. See the Playwright Python network guide.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
#1 Best Overall
Python asynchronous API
from playwright.async_api import async_playwright
async with async_playwright() as p:
browser = await p.chromium.launch()
page = await browser.new_page()
await page.goto("https://example.com")
async with page.expect_response(
lambda response: "/api/items" in response.url
and response.request.method == "GET"
) as response_info:
await page.get_by_role("button", name="Load items").click()
response = await response_info.value
print(response.status)
print(await response.text())
await browser.close()
JavaScript and TypeScript
Save the promise, trigger the request, then await the saved promise. Do not await the waiter before the click.
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto('https://example.com');
const responsePromise = page.waitForResponse(response =>
response.url().includes('/api/items') &&
response.request().method() === 'GET'
);
await page.getByRole('button', { name: 'Load items' }).click();
const response = await responsePromise;
console.log(response.status(), response.url());
console.log(await response.text());
await browser.close();
})();
The JavaScript API and matching rules are described in the Playwright JavaScript network guide and Page API.
Playwright: capture a stream of responses
Attach a listener before navigation or the action that creates traffic, then filter inside it.
def on_response(response):
if "/api/" in response.url:
print(response.status, response.url)
page.on("response", on_response)
page.goto("https://example.com")
# perform actions; the listener remains active
A response event means that status and headers have arrived. For a successful exchange, Playwright’s sequence is request, response, then requestfinished after the body has downloaded. A 404 or 503 is still an HTTP response; requestfailed describes a network- or client-level failure, not an HTTP error status. Use the response body method documented for your installed language binding. The Request API explains this lifecycle.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →Collecting bodies without losing events
Keep the handler small and hand work to your test’s async task or queue. For a single known call, a waiter is simpler because it gives you one response object and a bounded timeout. For broad capture, record URL, method, status and a timestamp, then consume each matched body after the request has finished.
Service workers and routing gaps
Service workers can make native routing appear to miss requests. For tests that must observe those calls, Playwright’s network guide recommends creating the context with service_workers="block". If you need the service worker to run, use BrowserContext-level events and identify responses handled by a service worker as described in the service-worker guide. Blocking changes application behavior, so choose it deliberately rather than treating it as a universal setting.
SeleniumBase: retrieve XHR bodies through CDP Mode
SeleniumBase’s documented raw_xhr_async.py recipe uses Chrome DevTools Protocol (CDP), not the ordinary WebDriver request API. The flow is:
- Register a handler for
Network.ResponseReceived. - Keep events whose resource type is
XHR. - Store each response URL and its request ID.
- Ask CDP for the body with
Network.getResponseBody(request_id). - Store both the body and the returned base64 indicator, and handle retrieval exceptions.
The following is the core of that documented async pattern. The names page and mycdp refer to the CDP page/session objects created by your installed SeleniumBase version; initialize them through the version’s cdp_driver.start_async() setup.
Free tools Windows power users keep installed
One-click scans. No signup required.
Rank #3
results = []
async def on_response(event):
if event.type != mycdp.network.ResourceType.XHR:
return
request_id = event.request_id
record = {"url": event.response.url, "request_id": request_id}
try:
body_result = await page.send(
mycdp.network.get_response_body(request_id)
)
record["body"] = body_result.body
record["base64_encoded"] = body_result.base64_encoded
except Exception as exc:
record["body_error"] = str(exc)
results.append(record)
page.add_handler(mycdp.network.ResponseReceived, on_response)
# Navigate and perform the action that generates XHR traffic here.
# Wait for your application's completion condition, then inspect results.
Use the complete example in SeleniumBase’s documented raw XHR example for session startup and shutdown. Its quiet-period loop is a batching strategy in that sample, not proof that a fixed delay captures every request. In production, prefer an application-specific completion signal or a bounded timeout.
CDP and WebDriver are different modes
SeleniumBase documents CDP Mode separately from WebDriver operation. Methods available in one mode may redirect, or have no CDP equivalent, when the browser is disconnected from WebDriver. Check the CDP Mode documentation and CDP Mode methods for your installed release instead of copying a WebDriver example into a CDP session.
Prevent races and make captures testable
- Install the waiter or handler before the click, form submit, navigation, or script call.
- Match a stable URL path plus HTTP method; include query parameters only when they are significant.
- Set a bounded timeout and report the predicate when it expires.
- For repeated calls, collect all matches and assert which one your test expects.
- Record status separately from transport failure so a 404 is not mislabeled as a missing response.
- When bodies are compressed, binary, or encoded, preserve the API’s returned representation instead of assuming UTF-8 JSON.
Troubleshooting
The Playwright waiter times out
Most often it was registered after the action, or its URL/method predicate is too narrow. Move registration above the trigger, log every response URL temporarily, and switch from an exact glob to a predicate or regular expression. Confirm that the request actually occurs in the browser context you are observing.
The event has headers but no usable body
The response event precedes body completion. Wait for request completion and then consume the response body through the response API. Do not treat the event callback itself as proof that downloading has finished.
A 404 or 503 appears as a response
That is expected: the server returned an HTTP response. Assert the status you require; reserve requestfailed handling for network/client failures.
Service-worker requests are missing
Either block service workers for the test context, as the network guide recommends, or observe BrowserContext events and account for service-worker ownership. Blocking can alter the page, so document the choice.
SeleniumBase cannot return a saved body
Ensure the response handler records the request ID before calling getResponseBody, and catch protocol exceptions. Body availability is timing-dependent; use a completion condition rather than an arbitrary short sleep. Verify that the browser is running in the CDP session used by the handler.
Or skip the browser setup
If your goal is a clean image or PDF rather than inspecting network payloads, ScreenshotNeo provides a single HTTP request. It accepts cookie or consent banners before capture and removes more than 60 known consent platforms, newsletter popups and chat widgets; each step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and response headers report the page verdict and billing state. Its MCP server includes take_screenshot, get_page_info and capture_pdf for Claude, Cursor and other MCP clients.
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 minutecurl -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 documentation for the other 63 capture options, including full-page lazy-image loading, CSS-selector elements, device and retina settings, custom JavaScript/CSS, request blocking, headers and cookies, signed links, webhooks and bulk capture.
Best Value
- Used Book in Good Condition
There is a free plan with 1,000 screenshots per month and no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.
Playwright or SeleniumBase?
Choose Playwright when your test needs a high-level response waiter, straightforward URL predicates and language-supported response objects. Choose SeleniumBase when your existing suite uses its CDP Mode and you need the protocol-level XHR event plus request-ID body retrieval. In either tool, correctness comes from registering before the trigger, matching deliberately and waiting for the body lifecycle you actually need.
FAQ
Can I capture fetch calls with the same Playwright API?
Yes. Playwright’s page response events cover browser responses; filter by URL or predicate rather than assuming the resource is specifically XHR.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Should a 404 fail the capture?
Not automatically. It is a received HTTP response, so capture it and assert status according to the behavior your test defines.
Is SeleniumBase’s quiet-period delay required?
No. It is the example’s batching technique. A task-specific completion signal with a maximum timeout is less dependent on arbitrary timing.
Where can I verify the exact SeleniumBase setup?
Use the raw XHR example together with the CDP Mode guide, because startup APIs vary with the installed SeleniumBase version.
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.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Fix the driver behind crashes, sound loss and screen glitches3Repair Windows errors before they cause bigger problems

