Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

To keep Chrome running after a Pyppeteer controller disconnects, keep alive the process that launched and owns Chrome, and call browser.disconnect() rather than a browser-closing method when you only want to stop controlling it. Save that running browser’s wsEndpoint so another client can connect. To send Chrome DevTools Protocol (CDP) commands, create a session from a Pyppeteer target with await target.createCDPSession(), then send protocol commands through the session.

Separate the browser’s lifetime from the controller’s

“Keep the browser open” can mean two different things: leave the Chrome or Chromium process running, or leave the Python script and its connection to that process running. They are not the same. A browser process can outlive one controller, but it needs a process or service that continues to own it. Disconnecting a client does not turn a browser launched by a short-lived script into a permanent service.

  • Browser process: the running Chrome or Chromium instance.
  • Browser connection: the client’s connection to that instance.
  • CDP session: a protocol connection attached to a particular target, such as a page.

Pyppeteer’s Browser API documents wsEndpoint as the browser’s WebSocket endpoint and disconnect() as disposing of the browser connection. Use the endpoint to connect another client while the same browser is still running. It is live connection information, not a permanent address: after a browser restart, obtain the endpoint for the new instance.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use a browser-closing operation only when the intention is to shut down the browser. If the owner process exits and that process was responsible for Chrome’s lifetime, the browser may exit too. The API documentation does not establish that a particular operating system, notebook, or process manager will preserve Chrome after its launcher exits; test the lifecycle in your own deployment.

Keep a Pyppeteer-launched browser available

A reliable pattern is to use one long-lived owner process to launch the browser and expose its endpoint to trusted clients. The owner remains alive; short-lived controller scripts connect, do work, and disconnect. This avoids confusing “stop controlling” with “stop the browser.”

Owner process

The following illustrates the lifecycle. It prints the endpoint and then waits instead of ending immediately. Keep the endpoint private: possession of it can permit access to the running browser, depending on the browser configuration and environment. The snippet is an architectural example; verify the installed Pyppeteer version’s launch and cleanup behavior before relying on it in production.

import asyncio
from pyppeteer import launch

async def main():
    browser = await launch(headless=False)
    print("Browser endpoint:", browser.wsEndpoint, flush=True)

    try:
        # This process owns the browser. Keep it running while clients need it.
        await asyncio.Event().wait()
    finally:
        # This owner is now intentionally shutting the browser down.
        await browser.close()

asyncio.get_event_loop().run_until_complete(main())

Run this in a persistent process or service appropriate to your environment. Store the printed endpoint somewhere accessible only to authorized clients; do not treat it as a reusable credential or check it into source control. When the owner is intentionally stopping and should terminate Chrome, its shutdown path can close the browser. When a separate controller merely finishes its work, that controller should disconnect instead.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Disconnect without asking the owner to close Chrome

If a script itself launched the browser and is about to finish, disconnecting is not by itself a robust way to keep Chrome alive after the launching process exits. Put the browser under a longer-lived owner, then use disconnect() from a client that should relinquish control. Pyppeteer’s documented distinction is between disconnecting the connection and closing the browser; check the exact installed release for details of process ownership and shutdown.

Rank #2
Sale
HTML and CSS: Design and Build Websites
  • HTML CSS Design and Build Web Sites
  • Comes with secure packaging
  • It can be a gift option
await browser.disconnect()

Do not substitute a close operation when the requirement is only to stop this client from controlling the still-needed browser. Conversely, do not leave an owner process running indefinitely if the browser should actually be shut down; give the owner a deliberate shutdown path and clean up resources according to the installed version’s API.

Connect a later controller using the WebSocket endpoint

A second script can connect to an already-running browser using the endpoint emitted by its owner. The Pyppeteer connection function and argument spelling should be checked against the installed release; the example below follows the documented shape surfaced for Pyppeteer, but the reference does not establish compatibility across every release.

import asyncio
from pyppeteer import connect

async def main():
    endpoint = "PASTE_CURRENT_BROWSER_WS_ENDPOINT_HERE"
    browser = await connect(browserWSEndpoint=endpoint)
    try:
        pages = await browser.pages()
        if not pages:
            raise RuntimeError("The connected browser has no open page targets")
        page = pages[0]
        print("Connected to page target:", page.url)
    finally:
        # End this controller's connection; the owner remains responsible
        # for the browser process.
        await browser.disconnect()

asyncio.get_event_loop().run_until_complete(main())

Use the endpoint from the browser instance that is currently running. If the owner restarts Chrome, it may expose a different endpoint; reconnecting with the old string will not revive the old instance. The example selects the first page returned, which may not be the page your application intends to control. In a real service, identify the desired target rather than assuming list order.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Create a CDP session from a Pyppeteer target

Pyppeteer’s API reference documents Target.createCDPSession() as creating a Chrome DevTools Protocol session attached to that target. The operation is asynchronous, so await it. A CDP session is target-specific; it is not a general-purpose method on every object, and a protocol command must be valid for the target and browser version in use.

import asyncio
from pyppeteer import connect

async def main():
    endpoint = "PASTE_CURRENT_BROWSER_WS_ENDPOINT_HERE"
    browser = await connect(browserWSEndpoint=endpoint)
    session = None

    try:
        pages = await browser.pages()
        if not pages:
            raise RuntimeError("No page target is available")

        page = pages[0]
        target = page.target
        session = await target.createCDPSession()

        result = await session.send("Browser.getVersion")
        print(result)
    finally:
        # Check the installed release for its supported session cleanup API.
        if session is not None:
            detach = getattr(session, "detach", None)
            if detach is not None:
                await detach()
        await browser.disconnect()

asyncio.get_event_loop().run_until_complete(main())

The session’s send method sends a CDP method name and, where applicable, parameters. Browser.getVersion is used here as a simple example of a browser-level protocol request. The returned value is protocol data; inspect the command’s protocol documentation for the fields and parameters relevant to your task. Pyppeteer’s Page implementation also uses CDP internally, so creating a session is a lower-level route rather than a replacement for ordinary Page methods.

Session cleanup is deliberately guarded in the example because the cited Pyppeteer reference supports creating sessions but does not establish one cleanup spelling for every installed release. Confirm the actual session API in your version. Keep the cleanup scopes conceptually separate: detach a session when finished with that target, and disconnect the browser client when that controller should stop communicating. Neither action should be confused with the owner’s decision to close Chrome.

What belongs to Pyppeteer, and what belongs to Puppeteer

Pyppeteer is the Python library in this workflow. Its API reference identifies Target.createCDPSession(); use that spelling and Python’s async/await model for Pyppeteer code. Puppeteer is the related JavaScript library and its documentation describes analogous concepts with its own API surface. Similarity between the projects is not evidence that a Puppeteer method name or lifecycle behavior is available in a particular Pyppeteer release. Check the installed package’s documentation and source when method names or cleanup behavior matter.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Common failures and how to recover

The browser exits when the script ends

Find which process launched Chrome and owns its lifetime. If that process exits, merely saving the endpoint or calling disconnect does not ensure the browser remains. Run the browser under a longer-lived owner or a separately managed browser service, and let short-lived clients connect to it. Test shutdown behavior in the environment you actually deploy.

Rank #4
Sale
Web Design with HTML, CSS, JavaScript and jQuery Set
  • Brand: Wiley
  • Set of 2 Volumes
  • A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers

A later client cannot connect

  • Confirm the owner is still running and Chrome has not exited.
  • Copy the endpoint from the current browser instance, not a previous run.
  • Check that the connection argument name is supported by the installed Pyppeteer version.
  • Confirm that the client can reach the endpoint in its network and security context. Do not expose a browser control endpoint to untrusted users.

There is no page in browser.pages()

The browser may be running without an open page target, or the target list may differ from what the script expects. Handle an empty list rather than indexing into it blindly. If your task concerns another target type, select that target explicitly and create the session from it.

The CDP command fails

Verify that the session is attached to the intended target and that the command is supported for that target and browser version. CDP method names and parameters are protocol operations, not arbitrary Pyppeteer Page methods. Consult the protocol definition applicable to the running browser and handle protocol errors in the controller.

Cleanup closes more than intended—or nothing gets cleaned up

Determine whether the code is the browser owner or only a connected controller. A controller should disconnect when it is done; the owner controls browser shutdown. Close or detach the CDP session using the cleanup method supported by the installed version. Add explicit cleanup paths for normal completion and exceptions so that a target session or owner process is not left unintentionally active.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If your goal is to obtain a website screenshot rather than control a persistent Chrome process or issue arbitrary CDP commands, ScreenshotNeo is a screenshot API and MCP server for developers. One GET request returns an image or PDF, without requiring you to maintain the browser lifecycle. Its API accepts a URL and can return PNG, JPEG, WebP, or PDF; its MCP tools include take_screenshot, get_page_info, and capture_pdf.

For example, using cURL:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

See the ScreenshotNeo API documentation for the request options and response behavior. Cookie and consent banners are accepted like a visitor and removed along with supported consent platforms, newsletter popups, and chat widgets before capture; those steps can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and responses indicate page verdict and billing status in headers. AI agents can use its MCP server. The Free plan includes 1,000 screenshots per month without a card; paid plans start at $5 for 3,000 shots. These are ScreenshotNeo plan terms, not a Pyppeteer capability.

Sign up for ScreenshotNeo’s free plan to get 1,000 screenshots a month with no card.

Frequently Asked Questions

Does browser.disconnect() close Chrome?

Pyppeteer documents it as disconnecting the browser connection. Whether Chrome remains available depends on the process that launched and owns it.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Can I reuse a Pyppeteer WebSocket endpoint after restarting Chrome?

No. Treat wsEndpoint as connection information for the currently running instance and obtain the new endpoint after a restart.

Is createCDPSession() a Pyppeteer Page method?

The Pyppeteer reference cited here documents Target.createCDPSession(); create the session from the target attached to the page.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.