100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Testing

Network Interception with page.route()

Learn how Playwright's page.route() and context.route() intercept, inspect, modify, fulfill, and abort network requests before they reach the real server.

Network & MockingIntermediate8 min readJul 10, 2026
Analogies

Understanding page.route() and Network Interception

Playwright's page.route(url, handler) lets you intercept every network request whose URL matches a pattern before it ever leaves the browser, giving your test the power to inspect, rewrite, fulfill, or abort it. This single API is the foundation for mocking third-party APIs, blocking analytics beacons, and simulating network failures without touching a real backend.

🏏

Cricket analogy: It is like a fielding coach reviewing every ball bowled in the nets before it reaches the batsman, deciding whether to let it through, swap it for a slower delivery, or stop the over entirely, the way Ravindra Jadeja might rehearse variations before a match.

Matching URLs and Route Patterns

page.route accepts a glob string, a regular expression, or a predicate function to decide which requests it should catch, and when multiple routes match the same URL, Playwright walks them in reverse registration order, last one added is tried first, until a handler calls route.continue(), route.fulfill(), or route.abort(). Because of this ordering, two overlapping routes can silently shadow one another if you aren't careful about registration order.

🏏

Cricket analogy: It is like a captain setting fielding restrictions for different overs of a T20 innings, the powerplay rule set applies first and can override the death-overs field placement if both are active at once, so the order they were set matters.

javascript
// Intercept and inspect a specific API path
await page.route('**/api/users/**', async (route) => {
  const request = route.request();
  console.log(request.method(), request.url());

  if (request.method() === 'GET') {
    // let the real request go through unmodified
    await route.continue();
  } else {
    // fulfill without hitting the real network
    await route.fulfill({
      status: 201,
      contentType: 'application/json',
      body: JSON.stringify({ id: 42, name: 'Test User' }),
    });
  }
});

Aborting and Continuing Requests

route.abort(errorCode) simulates network failure conditions such as 'failed', 'timedout', or 'connectionrefused', which is invaluable for testing offline banners, retry buttons, and error boundaries that are otherwise nearly impossible to trigger reliably. route.continue(overrides) does the opposite, letting the real request proceed to the network while optionally rewriting its headers, HTTP method, or postData before it leaves.

🏏

Cricket analogy: It is like a groundskeeper declaring a match abandoned due to a wet outfield in a rain-hit ODI at Eden Gardens, versus a match referee simply adjusting the target with Duckworth-Lewis and letting play continue.

Use page.unroute(url, handler) to remove a specific interception rule, or page.unrouteAll() to clear every route on that page. Forgetting to unroute between test cases in a shared fixture can cause routes registered by one test to leak into and unexpectedly affect the next.

Route Precedence and context.route()

context.route() registers an interception rule on every page opened within that BrowserContext, which is the right tool for global rules like blocking all requests to a third-party analytics domain across an entire test suite, whereas page.route() only affects the single page it was called on. When both a context-level and a page-level route match the same request, the more recently registered handler is tried first regardless of which level it was set at.

🏏

Cricket analogy: It is like a board-wide rule banning saliva use on the ball across every match in a series, versus a single umpire enforcing an extra local instruction only for the match they are standing in.

Every registered route handler must eventually call route.continue(), route.fulfill(), or route.abort(), or the request will hang and the test will time out. If a handler runs conditional logic, make sure all code paths reach one of these three terminal calls.

  • page.route() intercepts requests matching a URL glob, regex, or predicate before they hit the network.
  • Routes are matched in reverse registration order; the most recently added handler runs first.
  • route.continue(overrides) lets a real request proceed, optionally with modified headers, method, or body.
  • route.fulfill() returns a custom response without ever contacting the real server.
  • route.abort(errorCode) simulates network failures like 'failed' or 'timedout' for error-path testing.
  • context.route() applies globally to every page in a BrowserContext, unlike the page-scoped page.route().
  • Always resolve every handler with continue, fulfill, or abort to avoid hanging requests.

Practice what you learned

Was this page helpful?

Topics covered

#Testing#PlaywrightStudyNotes#TestingQA#NetworkInterceptionWithPageRoute#Network#Interception#Page#Route#Networking#StudyNotes#SkillVeris