You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Add Set Extra HTTP Headers keyword to change request headers mid-test #5115
Extra HTTP headers (auth tokens, correlation/tracing IDs, tenant selectors, feature-flag headers) can currently only be set once, at New Context time via extraHTTPHeaders. When a test obtains a fresh token mid-session — after login, after a token refresh, or when switching users — the only way to change headers today is to close the context and create a new one, which throws away all page state, cookies and open pages. Playwright allows updating the headers on a live context (or page) at any time; the library should too.
Proposed keyword / arguments
Set Extra HTTP Headers &{headers} *, scope=Context
headers — free named arguments (or a dict) of header name → value; applied to all subsequent requests. Header values must be strings.
scope — Context (default): headers apply to every page in the current context, including pages opened later; Page: only requests initiated by the current page (page-level headers are merged over context-level ones, per Playwright semantics).
New ContextNew Page${URL}/login
# ... perform login, obtain a token ...Set Extra HTTP Headers Authorization=Bearer ${token} X-Correlation-Id=${test_id}Go To${URL}/dashboard
# Override for the current page onlySet Extra HTTP Headers X-Experiment=variant-b scope=Page
New RPC in protobuf/playwright.proto carrying the header map plus a page/context flag.
node/playwright-wrapper: resolve current page or context from the catalog, call setExtraHTTPHeaders.
Python keyword (natural home: Browser/keywords/network.py or playwright_state.py), docs, atest asserting the header arrives server-side (test app echoes request headers) and that scope=Context covers a page opened after the call.
Backwards compatibility
Purely additive: a new keyword; the existing New Context extraHTTPHeaders= argument is untouched and simply provides the initial value the keyword can later replace.
Update after the Playwright 1.63–1.65 review (main at 5e35099)
Still not implemented. Nothing in node/playwright-wrapper calls setExtraHTTPHeaders. Headers can only be set at creation time, through extraHTTPHeaders on New Context (Browser/keywords/playwright_state.py:811) and New Persistent Context (playwright_state.py:1021). No atest covers extraHTTPHeaders, so the work for this issue should first add a test that the existing New Context argument reaches the server.
No API change in 1.63–1.65.browserContext.setExtraHTTPHeaders and page.setExtraHTTPHeaders have the same signatures and docs in 1.62 and 1.65.
The call replaces the whole set; it does not merge. Playwright's server code assigns the new map in place of the old one, and there is no getter for the current headers. For example, after New Context extraHTTPHeaders={'X-Tenant': 'a'}, the call Set Extra HTTP Headers Authorization=... stops sending X-Tenant. The keyword docs must say this, or the keyword must merge the new headers with the ones it already knows. Merging is possible only if the library tracks the headers per context.
scope already means something else in this library.scope is the Scope enum (Global, Suite, Test) for the lifetime of a setting (Browser/utils/data_types.py:1590, used by Set Browser Timeout, Set Strict Mode and others). Using scope=Context|Page for a different idea would confuse users. Use a different name for the context/page choice, or support only the context level. Only the context level matches the existing context setters Set Offline and Set Geolocation (node/playwright-wrapper/browser-control.ts:131,145), which is also the natural home for the Node side.
Headers now reach WebSocket handshakes. Playwright 1.63 added tests showing that extra HTTP headers are sent on the WebSocket handshake with Chromium 151 and later and with WebKit (test(websocket): cover setExtraHTTPHeaders and locale on the handshake request microsoft/playwright#42037). Firefox still does not send them for a WebSocket opened inside a Worker. This helps the token use case and should go in the keyword docs.
Basic auth has a separate API since 1.63.browserContext.setHTTPCredentials is no longer deprecated. It accepts an array of {username, password, origin} entries, so credentials can be limited to one origin and changed mid-test. An Authorization header set with setExtraHTTPHeaders goes to every origin the page calls, third-party origins included. The keyword docs should warn about this. If the request is really about Basic auth, credentials are a better fit than headers. The 1.65 fix that stops proxy credentials from answering website auth challenges (fix: do not send proxy credentials to website auth challenges microsoft/playwright#43482) does not affect headers.
Activity
aaltat commentedon Nov 7, 2026
Update after the Playwright 1.63–1.65 review (
mainat 5e35099)node/playwright-wrappercallssetExtraHTTPHeaders. Headers can only be set at creation time, throughextraHTTPHeadersonNew Context(Browser/keywords/playwright_state.py:811) andNew Persistent Context(playwright_state.py:1021). No atest coversextraHTTPHeaders, so the work for this issue should first add a test that the existingNew Contextargument reaches the server.browserContext.setExtraHTTPHeadersandpage.setExtraHTTPHeadershave the same signatures and docs in 1.62 and 1.65.New Context extraHTTPHeaders={'X-Tenant': 'a'}, the callSet Extra HTTP Headers Authorization=...stops sendingX-Tenant. The keyword docs must say this, or the keyword must merge the new headers with the ones it already knows. Merging is possible only if the library tracks the headers per context.scopealready means something else in this library.scopeis theScopeenum (Global,Suite,Test) for the lifetime of a setting (Browser/utils/data_types.py:1590, used bySet Browser Timeout,Set Strict Modeand others). Usingscope=Context|Pagefor a different idea would confuse users. Use a different name for the context/page choice, or support only the context level. Only the context level matches the existing context settersSet OfflineandSet Geolocation(node/playwright-wrapper/browser-control.ts:131,145), which is also the natural home for the Node side.setExtraHTTPHeadersandlocaleon the handshake request microsoft/playwright#42037). Firefox still does not send them for a WebSocket opened inside a Worker. This helps the token use case and should go in the keyword docs.browserContext.setHTTPCredentialsis no longer deprecated. It accepts an array of{username, password, origin}entries, so credentials can be limited to one origin and changed mid-test. AnAuthorizationheader set withsetExtraHTTPHeadersgoes to every origin the page calls, third-party origins included. The keyword docs should warn about this. If the request is really about Basic auth, credentials are a better fit than headers. The 1.65 fix that stops proxy credentials from answering website auth challenges (fix: do not send proxy credentials to website auth challenges microsoft/playwright#43482) does not affect headers.