--- id: network title: "Network" --- Playwright provides APIs to **monitor** and **modify** network traffic, both HTTP and HTTPS. Any requests that page does, including [XHRs](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) and [fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) requests, can be tracked, modified and handled.
## HTTP Authentication ```js const context = await browser.newContext({ httpCredentials: { username: 'bill', password: 'pa55w0rd', }, }); const page = await context.newPage(); await page.goto('https://example.com'); ``` ```java BrowserContext context = browser.newContext(new Browser.NewContextOptions() .setHttpCredentials("bill", "pa55w0rd")); Page page = context.newPage(); page.navigate("https://example.com"); ``` ```python async context = await browser.new_context( http_credentials={"username": "bill", "password": "pa55w0rd"} ) page = await context.new_page() await page.goto("https://example.com") ``` ```python sync context = browser.new_context( http_credentials={"username": "bill", "password": "pa55w0rd"} ) page = context.new_page() page.goto("https://example.com") ``` ### API reference - [`method: Browser.newContext`] ## HTTP Proxy You can configure pages to load over the HTTP(S) proxy or SOCKSv5. Proxy can be either set globally for the entire browser, or for each browser context individually. You can optionally specify username and password for HTTP(S) proxy, you can also specify hosts to bypass proxy for. Here is an example of a global proxy: ```js const browser = await chromium.launch({ proxy: { server: 'http://myproxy.com:3128', user: 'usr', password: 'pwd' } }); ``` ```java Browser browser = chromium.launch(new BrowserType.LaunchOptions() .setProxy(new Proxy("http://myproxy.com:3128") .setUsername('usr') .setPassword('pwd')); ``` ```python async browser = await chromium.launch(proxy={ "server": "http://myproxy.com:3128", "user": "usr", "password": "pwd" }) ``` ```python sync browser = chromium.launch(proxy={ "server": "http://myproxy.com:3128", "user": "usr", "password": "pwd" }) ``` When specifying proxy for each context individually, you need to give Playwright a hint that proxy will be set. This is done via passing a non-empty proxy server to the browser itself. Here is an example of a context-specific proxy: ```js const browser = await chromium.launch({ proxy: { server: 'per-context' } }); const context = await browser.newContext({ proxy: { server: 'http://myproxy.com:3128' } }) ``` ```java Browser browser = chromium.launch(new BrowserType.LaunchOptions() .setProxy(new Proxy("per-context")); BrowserContext context = chromium.launch(new Browser.NewContextOptions() .setProxy(new Proxy("http://myproxy.com:3128")); ``` ```python async browser = await chromium.launch(proxy={"server": "per-context"}) context = await browser.new_context(proxy={"server": "http://myproxy.com:3128"}) ``` ```python sync browser = chromium.launch(proxy={"server": "per-context"}) context = browser.new_context(proxy={"server": "http://myproxy.com:3128"}) ``` ## Network events You can monitor all the requests and responses: ```js const { chromium, webkit, firefox } = require('playwright'); (async () => { const browser = await chromium.launch(); const page = await browser.newPage(); // Subscribe to 'request' and 'response' events. page.on('request', request => console.log('>>', request.method(), request.url())); page.on('response', response => console.log('<<', response.status(), response.url())); await page.goto('https://example.com'); await browser.close(); })(); ``` ```java import com.microsoft.playwright.*; public class Example { public static void main(String[] args) { try (Playwright playwright = Playwright.create()) { BrowserType chromium = playwright.chromium(); Browser browser = chromium.launch(); Page page = browser.newPage(); page.onRequest(request -> System.out.println(">> " + request.method() + " " + request.url())); page.onResponse(response -> System.out.println("<<" + response.status() + " " + response.url())); page.navigate("https://example.com"); browser.close(); } } } ``` ```python async import asyncio from playwright.async_api import async_playwright async def run(playwright): chromium = playwright.chromium browser = await chromium.launch() page = await browser.new_page() # Subscribe to "request" and "response" events. page.on("request", lambda request: print(">>", request.method, request.url)) page.on("response", lambda response: print("<<", response.status, response.url)) await page.goto("https://example.com") await browser.close() async def main(): async with async_playwright() as playwright: await run(playwright) asyncio.run(main()) ``` ```python sync from playwright.sync_api import sync_playwright def run(playwright): chromium = playwright.chromium browser = chromium.launch() page = browser.new_page() # Subscribe to "request" and "response" events. page.on("request", lambda request: print(">>", request.method, request.url)) page.on("response", lambda response: print("<<", response.status, response.url)) page.goto("https://example.com") browser.close() with sync_playwright() as playwright: run(playwright) ``` Or wait for a network response after the button click: ```js // Use a glob URL pattern const [response] = await Promise.all([ page.waitForResponse('**/api/fetch_data'), page.click('button#update'), ]); ``` ```java // Use a glob URL pattern Response response = page.waitForResponse("**/api/fetch_data", () -> { page.click("button#update"); }); ``` ```python async # Use a glob url pattern async with page.expect_response("**/api/fetch_data") as response_info: await page.click("button#update") response = await response_info.value ``` ```python sync # Use a glob url pattern with page.expect_response("**/api/fetch_data") as response_info: page.click("button#update") response = response_info.value ``` #### Variations ```js // Use a RegExp const [response] = await Promise.all([ page.waitForResponse(/\.jpeg$/), page.click('button#update'), ]); // Use a predicate taking a Response object const [response] = await Promise.all([ page.waitForResponse(response => response.url().includes(token)), page.click('button#update'), ]); ``` ```java // Use a RegExp Response response = page.waitForResponse(Pattern.compile("\\.jpeg$"), () -> { page.click("button#update"); }); // Use a predicate taking a Response object Response response = page.waitForResponse(r -> r.url().contains(token), () -> { page.click("button#update"); }); ``` ```python async # Use a regular expression async with page.expect_response(re.compile(r"\.jpeg$")) as response_info: await page.click("button#update") response = await response_info.value # Use a predicate taking a response object async with page.expect_response(lambda response: token in response.url) as response_info: await page.click("button#update") response = await response_info.value ``` ```python sync # Use a regular expression with page.expect_response(re.compile(r"\.jpeg$")) as response_info: page.click("button#update") response = response_info.value # Use a predicate taking a response object with page.expect_response(lambda response: token in response.url) as response_info: page.click("button#update") response = response_info.value ``` ### API reference - [Request] - [Response] - [`event: Page.request`] - [`event: Page.response`] - [`method: Page.waitForRequest`] - [`method: Page.waitForResponse`]
## Handle requests ```js await page.route('**/api/fetch_data', route => route.fulfill({ status: 200, body: testData, })); await page.goto('https://example.com'); ``` ```java page.route("**/api/fetch_data", route -> route.fulfill(new Route.FulfillOptions() .setStatus(200) .setBody(testData))); page.navigate("https://example.com"); ``` ```python async await page.route( "**/api/fetch_data", lambda route: route.fulfill(status=200, body=test_data)) await page.goto("https://example.com") ``` ```python sync page.route( "**/api/fetch_data", lambda route: route.fulfill(status=200, body=test_data)) page.goto("https://example.com") ``` You can mock API endpoints via handling the network quests in your Playwright script. #### Variations ```js // Set up route on the entire browser context. // It will apply to popup windows and opened links. await browserContext.route('**/api/login', route => route.fulfill({ status: 200, body: 'accept', })); await page.goto('https://example.com'); ``` ```java browserContext.route("**/api/login", route -> route.fulfill(new Route.FulfillOptions() .setStatus(200) .setBody("accept"))); page.navigate("https://example.com"); ``` ```python async # Set up route on the entire browser context. # It will apply to popup windows and opened links. await context.route( "**/api/login", lambda route: route.fulfill(status=200, body="accept")) await page.goto("https://example.com") ``` ```python sync # Set up route on the entire browser context. # It will apply to popup windows and opened links. context.route( "**/api/login", lambda route: route.fulfill(status=200, body="accept")) page.goto("https://example.com") ``` ### API reference - [`method: BrowserContext.route`] - [`method: BrowserContext.unroute`] - [`method: Page.route`] - [`method: Page.unroute`] - [Route]
## Modify requests ```js // Delete header await page.route('**/*', route => { const headers = route.request().headers(); delete headers['X-Secret']; route.continue({headers}); }); // Continue requests as POST. await page.route('**/*', route => route.continue({method: 'POST'})); ``` ```java // Delete header page.route("**/*", route -> { Map headers = new HashMap<>(route.request().headers()); headers.remove("X-Secret"); route.resume(new Route.ResumeOptions().setHeaders(headers)); }); // Continue requests as POST. page.route("**/*", route -> route.resume(new Route.ResumeOptions().setMethod("POST"))); ``` ```python async # Delete header async def handle_route(route): headers = route.request.headers del headers["x-secret"] route.continue_(headers=headers) await page.route("**/*", handle_route) # Continue requests as POST. await page.route("**/*", lambda route: route.continue_(method="POST")) ``` ```python sync # Delete header def handle_route(route): headers = route.request.headers del headers["x-secret"] route.continue_(headers=headers) page.route("**/*", handle_route) # Continue requests as POST. page.route("**/*", lambda route: route.continue_(method="POST")) ``` You can continue requests with modifications. Example above removes an HTTP header from the outgoing requests. ## Abort requests ```js await page.route('**/*.{png,jpg,jpeg}', route => route.abort()); // Abort based on the request type await page.route('**/*', route => { return route.request().resourceType() === 'image' ? route.abort() : route.continue(); }); ``` ```java page.route("**/*.{png,jpg,jpeg}", route -> route.abort()); // Abort based on the request type page.route("**/*", route -> { if ("image".equals(route.request().resourceType())) route.abort(); else route.resume(); }); ``` ```python async await page.route("**/*.{png,jpg,jpeg}", lambda route: route.abort()) # Abort based on the request type await page.route("**/*", lambda route: route.abort() if route.request.resource_type == "image" else route.continue_()) ``` ```python sync page.route("**/*.{png,jpg,jpeg}", lambda route: route.abort()) # Abort based on the request type page.route("**/*", lambda route: route.abort() if route.request.resource_type == "image" else route.continue_()) ``` ### API reference - [`method: Page.route`] - [`method: BrowserContext.route`] - [`method: Route.abort`]
## WebSockets Playwright supports [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API) inspection out of the box. Every time WebSocket is created, [`event: Page.webSocket`] event is fired. This event contains the [WebSocket] instance for further web socket frames inspection: ```js page.on('websocket', ws => { console.log(`WebSocket opened: ${ws.url()}>`); ws.on('framesent', event => console.log(event.payload)); ws.on('framereceived', event => console.log(event.payload)); ws.on('close', () => console.log('WebSocket closed')); }); ``` ```java page.onWebSocket(ws -> { log("WebSocket opened: " + ws.url()); ws.onFrameSent(frameData -> log(frameData.text())); ws.onFrameReceived(frameData -> log(frameData.text())); ws.onClose(ws1 -> log("WebSocket closed")); }); ``` ```python def on_web_socket(ws): print(f"WebSocket opened: {ws.url}") ws.on("framesent", lambda payload: print(payload)) ws.on("framereceived", lambda payload: print(payload)) ws.on("close", lambda payload: print("WebSocket closed")) page.on("websocket", on_web_socket) ``` ### API reference - [WebSocket] - [`event: Page.webSocket`] - [`event: WebSocket.frameSent`] - [`event: WebSocket.frameReceived`] - [`event: WebSocket.close`]