2021-01-01 15:17:27 -08:00
|
|
|
---
|
|
|
|
id: network
|
|
|
|
title: "Network"
|
|
|
|
---
|
2020-12-30 18:04:51 -08:00
|
|
|
|
2021-01-14 15:01:39 -08:00
|
|
|
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
|
2020-12-30 18:04:51 -08:00
|
|
|
[fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) requests, can be tracked, modified and handled.
|
|
|
|
|
2021-01-01 15:17:27 -08:00
|
|
|
<!-- TOC -->
|
2020-12-30 18:04:51 -08:00
|
|
|
|
|
|
|
<br/>
|
|
|
|
|
|
|
|
## HTTP Authentication
|
|
|
|
|
|
|
|
```js
|
|
|
|
const context = await browser.newContext({
|
|
|
|
httpCredentials: {
|
|
|
|
username: 'bill',
|
|
|
|
password: 'pa55w0rd',
|
|
|
|
},
|
|
|
|
});
|
|
|
|
const page = await context.newPage();
|
|
|
|
await page.goto('https://example.com');
|
|
|
|
```
|
|
|
|
|
2021-03-01 09:18:44 -08:00
|
|
|
```java
|
|
|
|
BrowserContext context = browser.newContext(new Browser.NewContextOptions()
|
|
|
|
.withHttpCredentials("bill", "pa55w0rd"));
|
|
|
|
Page page = context.newPage();
|
|
|
|
page.navigate("https://example.com");
|
|
|
|
```
|
|
|
|
|
2021-01-14 15:01:39 -08:00
|
|
|
```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")
|
|
|
|
```
|
2020-12-30 18:04:51 -08:00
|
|
|
|
2021-01-17 21:09:40 -08:00
|
|
|
### API reference
|
2020-12-30 18:04:51 -08:00
|
|
|
- [`method: Browser.newContext`]
|
|
|
|
|
|
|
|
## 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();
|
|
|
|
})();
|
|
|
|
```
|
|
|
|
|
2021-03-01 09:18:44 -08:00
|
|
|
```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();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2021-01-14 15:01:39 -08:00
|
|
|
```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)
|
|
|
|
```
|
|
|
|
|
2020-12-30 18:04:51 -08:00
|
|
|
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'),
|
|
|
|
]);
|
|
|
|
```
|
|
|
|
|
2021-03-01 09:18:44 -08:00
|
|
|
```java
|
|
|
|
// Use a glob URL pattern
|
|
|
|
Response response = page.waitForResponse("**/api/fetch_data", () -> {
|
|
|
|
page.click("button#update");
|
|
|
|
});
|
|
|
|
```
|
|
|
|
|
2021-01-14 15:01:39 -08:00
|
|
|
```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
|
|
|
|
```
|
|
|
|
|
2020-12-30 18:04:51 -08:00
|
|
|
#### 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'),
|
|
|
|
]);
|
|
|
|
```
|
|
|
|
|
2021-03-01 09:18:44 -08:00
|
|
|
```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");
|
|
|
|
});
|
|
|
|
```
|
|
|
|
|
2021-01-14 15:01:39 -08:00
|
|
|
```python async
|
2021-01-15 16:01:41 -08:00
|
|
|
# Use a regular expression
|
2021-01-14 15:01:39 -08:00
|
|
|
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
|
2021-01-15 16:01:41 -08:00
|
|
|
# Use a regular expression
|
2021-01-14 15:01:39 -08:00
|
|
|
with page.expect_response(re.compile(r"\.jpeg$")) as response_info:
|
|
|
|
page.click("button#update")
|
|
|
|
response = response_info.value
|
2020-12-30 18:04:51 -08:00
|
|
|
|
2021-01-14 15:01:39 -08:00
|
|
|
# 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
|
|
|
|
```
|
|
|
|
|
2021-01-17 21:09:40 -08:00
|
|
|
### API reference
|
2020-12-30 18:04:51 -08:00
|
|
|
- [Request]
|
|
|
|
- [Response]
|
|
|
|
- [`event: Page.request`]
|
|
|
|
- [`event: Page.response`]
|
|
|
|
- [`method: Page.waitForRequest`]
|
|
|
|
- [`method: Page.waitForResponse`]
|
|
|
|
|
|
|
|
<br/>
|
|
|
|
|
|
|
|
## Handle requests
|
|
|
|
|
|
|
|
```js
|
|
|
|
await page.route('**/api/fetch_data', route => route.fulfill({
|
|
|
|
status: 200,
|
|
|
|
body: testData,
|
|
|
|
}));
|
|
|
|
await page.goto('https://example.com');
|
|
|
|
```
|
|
|
|
|
2021-03-01 09:18:44 -08:00
|
|
|
```java
|
|
|
|
page.route("**/api/fetch_data", route -> route.fulfill(new Route.FulfillOptions()
|
|
|
|
.withStatus(200)
|
|
|
|
.withBody(testData)));
|
|
|
|
page.navigate("https://example.com");
|
|
|
|
```
|
|
|
|
|
2021-01-14 15:01:39 -08:00
|
|
|
```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")
|
|
|
|
```
|
|
|
|
|
2020-12-30 18:04:51 -08:00
|
|
|
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');
|
|
|
|
```
|
|
|
|
|
2021-03-01 09:18:44 -08:00
|
|
|
```java
|
|
|
|
browserContext.route("**/api/login", route -> route.fulfill(new Route.FulfillOptions()
|
|
|
|
.withStatus(200)
|
|
|
|
.withBody("accept")));
|
|
|
|
page.navigate("https://example.com");
|
|
|
|
```
|
|
|
|
|
2021-01-14 15:01:39 -08:00
|
|
|
```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")
|
|
|
|
```
|
2020-12-30 18:04:51 -08:00
|
|
|
|
2021-01-17 21:09:40 -08:00
|
|
|
### API reference
|
2020-12-30 18:04:51 -08:00
|
|
|
- [`method: BrowserContext.route`]
|
|
|
|
- [`method: BrowserContext.unroute`]
|
|
|
|
- [`method: Page.route`]
|
|
|
|
- [`method: Page.unroute`]
|
|
|
|
- [Route]
|
|
|
|
|
|
|
|
<br/>
|
|
|
|
|
|
|
|
## 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'}));
|
|
|
|
```
|
|
|
|
|
2021-03-01 09:18:44 -08:00
|
|
|
```java
|
|
|
|
// Delete header
|
|
|
|
page.route("**/*", route -> {
|
|
|
|
Map<String, String> headers = new HashMap<>(route.request().headers());
|
|
|
|
headers.remove("X-Secret");
|
|
|
|
route.resume(new Route.ResumeOptions().withHeaders(headers));
|
|
|
|
});
|
|
|
|
|
|
|
|
// Continue requests as POST.
|
|
|
|
page.route("**/*", route -> route.resume(new Route.ResumeOptions().withMethod("POST")));
|
|
|
|
```
|
|
|
|
|
2021-01-14 15:01:39 -08:00
|
|
|
```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"))
|
|
|
|
```
|
|
|
|
|
2020-12-30 18:04:51 -08:00
|
|
|
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();
|
|
|
|
});
|
|
|
|
```
|
|
|
|
|
2021-03-01 09:18:44 -08:00
|
|
|
```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();
|
|
|
|
});
|
|
|
|
```
|
|
|
|
|
2021-01-14 15:01:39 -08:00
|
|
|
```python async
|
|
|
|
await page.route("**/*.{png,jpg,jpeg}", lambda route: route.abort())
|
2020-12-30 18:04:51 -08:00
|
|
|
|
2021-01-14 15:01:39 -08:00
|
|
|
# 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_())
|
|
|
|
```
|
|
|
|
|
2021-01-17 21:09:40 -08:00
|
|
|
### API reference
|
2020-12-30 18:04:51 -08:00
|
|
|
- [`method: Page.route`]
|
|
|
|
- [`method: BrowserContext.route`]
|
|
|
|
- [`method: Route.abort`]
|
|
|
|
|
2021-01-14 15:01:39 -08:00
|
|
|
<br/>
|