How Playwright connects to remote browsers.
Playwright clients use two remote attachment protocols. Native connect uses Playwright transport. connectOverCDP uses lower-fidelity, Chromium-only CDP. Native client and server major and minor versions must match. Patch versions may differ.
Playwright 1.59 added browser.bind(). A producer can bind a launched browser. Named pipes work locally. The WebSocket example requires Playwright 1.60 or newer.
Legba's proposed preview docs publish neither connection contract. No Playwright WebSocket is currently documented. No CDP endpoint is currently documented.
Residential routing uses a separate network contract. BrowserContext state never proves proxy behavior.
The short version
A remote URL is not compatibility.
Remote Playwright starts with a protocol contract.
Playwright normally launches browsers on the same machine. Remote operation changes that ownership boundary. A browser server owns the browser process. Your application owns the Playwright client.
Playwright's native connect method attaches remotely. A BrowserServer can produce its endpoint. Playwright 1.59 lets a launched Browser create one. It uses browser.bind().
The endpoint must match Playwright's protocol. Any WebSocket address is insufficient. A Chrome debugging socket is different. A browser viewing URL is also different.
Connection success proves protocol compatibility. It does not prove task reliability. State, artifacts, timeouts, and cleanup still matter. Evaluate the whole operating contract.
- Identify the exact connection method.
- Identify the endpoint protocol.
- Record client and server versions.
- Separate browser ownership from client ownership.
- Define post-disconnection cleanup.
- Test one representative workflow.
Bind a launched browser for other clients.
Playwright 1.59 added browser.bind(). It makes a launched browser available to other Playwright clients.
The default binding uses a named pipe. Host and port create a WebSocket endpoint. Port zero lets the operating system choose an available port. Playwright 1.59.1 returned a malformed WebSocket endpoint. The corrected construction appears in Playwright 1.60.
Browser.bind creates producer-side access. BrowserType.connect performs consumer-side attachment. connectOverCDP remains a different Chromium-only protocol.
Browser.unbind stops new connections. Keep every exposed endpoint inside a trusted boundary.
- Use named pipes for local attachment.
- Use host and port for WebSockets.
- Treat bind as the producer step.
- Treat connect as the consumer step.
- Use unbind to stop new clients.
import { chromium } from "playwright"
const producer = await chromium.launch()
const { endpoint } = await producer.bind("shared-browser", {
host: "127.0.0.1",
port: 0,
})
const consumer = await chromium.connect(endpoint)
// Run trusted work through the connected client.
await consumer.close()
await producer.unbind()
await producer.close()SourcesPlaywright BrowserPlaywright BrowserTypePlaywright 1.59.1 WebSocket bind issuePlaywright 1.60 browser bind source
Legba's proposed preview documents a different contract.
Legba publishes a proposed public-preview contract. It provides illustrative endpoint shapes. It publishes no callable host or key issuer. Do not treat the examples as a live service.
The proposed docs sketch REST instance lifecycle. They show create, list, and destroy operations. These examples describe a possible contract, not currently callable endpoints.
Illustrative responses include an access_url. The proposal never defines a Playwright protocol. It never defines a CDP protocol.
Therefore, current Playwright compatibility is undocumented. An illustrative access_url cannot establish compatibility alone. Wait for an explicit protocol contract. Recheck canonical docs before implementation.
| Factor | Documented today | Not documented today | Engineering consequence |
|---|---|---|---|
| REST lifecycle | Illustrative create, list, and destroy contract. | Playwright browser command transport. | Evaluate lifecycle separately from automation. |
| Instance access | Illustrative responses include an access_url. | Access URL protocol semantics. | Never convert fields into guessed endpoints. |
| REST authentication | A bearer API-key pattern is proposed. | Browser-channel authentication requirements. | Do not reuse assumptions across channels. |
| Playwright compatibility | No current compatibility claim exists. | Native WebSocket or CDP endpoints. | Keep Playwright integration unimplemented. |
Legba's proposed documentation supports limited conclusions.
SourcesLegba API documentationLegba Instances APILegba API quickstartLegba API authenticationPlaywright BrowserType
Choose the connection path deliberately.
Playwright exposes two relevant remote attachment methods. They do not offer equivalent behavior. Native connect speaks Playwright's protocol. connectOverCDP speaks Chrome DevTools Protocol.
Native connect requires compatible Playwright versions. Client and server major versions must match. Minor versions must also match. Patch versions may differ.
connectOverCDP supports Chromium browsers only. Official documentation describes significantly lower fidelity. Some Playwright capabilities may behave differently. Native protocol remains the stronger default.
A provider's REST URL is neither path automatically. The provider must name the transport. It must document authentication and versions. Otherwise, compatibility remains unknown.
| Factor | Connection contract | Best fit | Required proof | Main tradeoff |
|---|---|---|---|---|
| Native Playwright protocol | Fuller Playwright feature fidelity. | A Playwright WebSocket endpoint. | Matching major-minor Playwright versions. | Server version constrains client upgrades. |
| Bound Playwright browser | Sharing a launched browser with trusted clients. | A named pipe or WebSocket from browser.bind(). | Playwright 1.60 or newer for host-and-port WebSockets. | The producer owns browser lifecycle. |
| Chrome DevTools Protocol | Chromium systems exposing CDP. | A documented CDP endpoint. | Chromium-only browser compatibility. | Playwright documents lower fidelity. |
| Local browser launch | Local development and controlled runners. | Installed browser and runtime access. | Application owns browser process lifecycle. | Compute remains application-managed. |
| REST instance access | Provider lifecycle and browser viewing. | Exact documented access semantics. | No implied Playwright compatibility. | Automation may require another contract. |
A decision matrix for Playwright remote connections.
SourcesPlaywright BrowserTypePlaywright BrowserPlaywright 1.59.1 WebSocket bind issuePlaywright 1.60 browser bind sourceLegba Instances API
Residential routing is a separate contract.
A Playwright connection controls browser commands. It does not choose an IP source. Playwright documents generic HTTP and SOCKS proxies. It does not provide residential network service.
BrowserContext isolates cookies and local storage. A new context alone promises no new IP. Proxy configuration controls network egress. Provider sessions define reuse and rotation.
Remote providers place proxy settings differently. Browserbase uses session creation. Browserless uses connection parameters. Follow each provider's current contract.
Legba's proposed preview sketches REST instance lifecycle. It publishes no Playwright or CDP endpoint. It publishes no proxy or geography field. Do not infer a residential Playwright integration.
- Verify the browser connection protocol separately.
- Inspect egress from inside the browser.
- Repeat checks across pages, contexts, and sessions.
- Compare requested geography with observed geography.
- Record proxy reuse and rotation behavior.
- Keep proxy credentials outside source code.
- Review provider restrictions and bandwidth charges.
- Stop when a required contract remains undocumented.
| Factor | Contract surface | Operational boundary | Required proof |
|---|---|---|---|
| Transport | Playwright WebSocket or CDP attachment. | Browser commands and protocol fidelity. | Documented endpoint, authentication, and version behavior. |
| Browser state | BrowserContext cookies and local storage. | Session data inside the browser. | Fresh context state and explicit cleanup. |
| Network egress | HTTP or SOCKS proxy routing. | Exit source, geography, reuse, and rotation. | Observed egress across contexts and provider sessions. |
Three contracts govern a residential Playwright workflow.
SourcesPlaywright BrowserTypePlaywright BrowserContextPlaywright isolation guidePlaywright network guideBrowserbase proxy documentationBrowserless proxy documentation
import { chromium } from "playwright"
const browser = await chromium.launch({
proxy: {
server: process.env.PLAYWRIGHT_PROXY_SERVER!,
username: process.env.PLAYWRIGHT_PROXY_USERNAME!,
password: process.env.PLAYWRIGHT_PROXY_PASSWORD!,
},
})
const context = await browser.newContext()
const page = await context.newPage()
await page.goto("https://example.com")
await context.close()
await browser.close()SourcesLegba Instances API
Use a provider-neutral native connection pattern.
The following pattern mirrors Playwright's documented method. It deliberately uses a generic environment variable. Replace it only with provider documentation. Never transform an unrelated access URL.
The client connects before creating a context. That context receives its own pages. The example closes context resources explicitly. It then closes the connected browser object.
This example is provider-neutral. It uses a placeholder endpoint. It was not tested against Legba. It does not prove Legba compatibility.
Production code needs provider-specific lifecycle handling. It also needs retries and artifact capture. Those details depend on published contracts. Keep them outside generic connection helpers.
- Keep endpoint values outside source code.
- Match client and server versions.
- Create explicit browser contexts.
- Close contexts before disconnecting.
- Separate provider resource cleanup.
- Never label this Legba-compatible.
import { chromium } from "playwright"
const browser = await chromium.connect(
process.env.PLAYWRIGHT_WS_ENDPOINT!,
)
const context = await browser.newContext()
const page = await context.newPage()
await page.goto("https://example.com")
await context.close()
await browser.close()SourcesPlaywright BrowserTypePlaywright BrowserContextPlaywright Browser
Treat browser state as sensitive infrastructure.
Playwright browser contexts provide independent sessions. They isolate cookies and local storage. Multiple contexts can share one browser. Each context still needs explicit ownership.
Authentication state can reduce repeated login work. Playwright stores reusable state through storageState. That file may contain sensitive cookies. It may also contain sensitive headers.
Playwright recommends keeping state outside repositories. Add its directory to version-control exclusions. Delete expired state when appropriate. Never expose reusable state through client bundles.
Remote providers add another storage boundary. Ask where context data resides. Ask whether profiles persist after termination. Ask how deletion is verified. Document every answer before reuse.
| Factor | State choice | Operational benefit | Required safeguard |
|---|---|---|---|
| Fresh context | Starts with isolated browser state. | Improves task repeatability. | Close every context explicitly. |
| Stored authentication state | Avoids repeated login setup. | Reduces test preparation time. | Protect cookies and sensitive headers. |
| Provider profile | May preserve browser state remotely. | Depends entirely on provider contracts. | Verify retention and deletion behavior. |
| Shared default context | May expose existing browser state. | Changes isolation assumptions. | Inspect provider context semantics first. |
State choices change security and repeatability.
SourcesPlaywright BrowserContextPlaywright authenticationLegba Instances API
Design artifacts before failures happen.
Remote debugging needs durable evidence. A local stack trace may be insufficient. Browser actions happened elsewhere. Network timing and page state can disappear quickly.
Playwright tracing records browser operations. Trace Viewer exposes actions and metadata. Traces can include screenshots and snapshots. Their contents may include sensitive application data.
Playwright Test supports retry-focused tracing. Official guidance recommends tracing the first retry. That balances evidence against performance costs. Plain library usage requires explicit tracing calls.
Artifact transfer remains provider-specific. Ask where trace files are written. Ask whether disconnection preserves them. Ask when downloads become available. Test retrieval during partial failures.
- 01
Choose required failure evidence.
List traces, logs, screenshots, and downloads. Assign retention needs.
- 02
Enable artifacts intentionally.
Capture evidence around representative failures. Avoid unbounded collection.
- 03
Interrupt the client process.
Confirm provider-side artifacts remain retrievable. Record missing evidence.
- 04
Review sensitive contents.
Treat traces as potentially sensitive. Restrict storage and sharing.
Separate connection cleanup from resource cleanup.
Playwright exposes browser and context lifecycle methods. The browser close method clears connected contexts. It then disconnects the client. Close contexts first for orderly artifact flushing.
Provider infrastructure may have another lifecycle. A disconnected client may leave resources active. The provider's REST contract must own termination. Browser closure never proves provider termination.
Failures can occur between every cleanup step. Context closure can fail. Client disconnection can race network loss. Provider termination can also fail independently.
Use resource identifiers for reconciliation. List remaining resources after interruptions. Retry only documented safe operations. Confirm a final terminated state. Keep browser errors and lifecycle errors separate.
| Factor | Cleanup layer | Responsible interface | Verification evidence |
|---|---|---|---|
| Page work | Application and Playwright page APIs. | Finish outputs before context closure. | Required artifacts are retrievable. |
| Browser context | Playwright BrowserContext owns pages. | Close the context explicitly. | Context pages are closed. |
| Client connection | Connected Browser owns client attachment. | Close after context cleanup. | The client becomes disconnected. |
| Provider resource | Provider lifecycle contract owns infrastructure. | Call documented termination separately. | Resource status confirms termination. |
Cleanup layers have separate owners.
SourcesPlaywright BrowserContextPlaywright BrowserLegba Instances APILegba API errors
Prove the contract before migration.
Begin with one production-shaped Playwright task. Include navigation and authentication. Include expected outputs and artifacts. Include a normal failure path.
Write compatibility requirements before choosing providers. Name the desired connection method. Name the supported browser engines. Name acceptable version constraints.
Legba's proposed lifecycle contract is a design reference only. It lacks Playwright protocol details. It also lacks CDP endpoint details. Current evidence cannot justify implementation.
Return after published compatibility appears. Then test the exact documented endpoint. Pin compatible Playwright versions. Recheck documentation before each upgrade. Keep guessed endpoints out of production.
- 01
Define the protocol requirement.
Choose native Playwright or CDP. Record required browser engines.
- 02
Require published provider evidence.
Verify endpoint type, authentication, and versions. Record remaining unknowns.
- 03
Run one representative task.
Exercise state, artifacts, downloads, and cleanup. Preserve failure evidence.
- 04
Interrupt every lifecycle layer.
Test connection loss and client failure. Reconcile provider resources afterward.
- 05
Review the current preview.
Recheck canonical Legba documentation. Wait for explicit Playwright compatibility.
SourcesLegba API documentationLegba API quickstartLegba Instances APIPlaywright BrowserType
FAQs.
What does Playwright browser.bind() do?
How does Playwright connect remotely?
Must Playwright versions match?
What does connectOverCDP support?
Does Legba support Playwright today?
Does the browser close method terminate provider infrastructure?
Does Playwright provide residential IPs?
Does a new BrowserContext guarantee a new IP?
References
- 01
- 02Legba API quickstartLegba
- 03Legba Instances APILegba
- 04
- 05Legba API errorsLegba
- 06Playwright BrowserTypeMicrosoft Playwright
- 07Playwright BrowserMicrosoft Playwright
- 08Playwright BrowserContextMicrosoft Playwright
- 09Playwright authenticationMicrosoft Playwright
- 10Playwright Trace ViewerMicrosoft Playwright
- 11Playwright network guideMicrosoft Playwright
- 12Playwright isolation guideMicrosoft Playwright
- 13Playwright 1.59.1 WebSocket bind issueMicrosoft Playwright
- 14Playwright 1.60 browser bind sourceMicrosoft Playwright
- 15Browserbase proxy documentationBrowserbase
- 16Browserless proxy documentationBrowserless