Skip to content

Use custom_display_url (or a dedicated public URL) for open_browser #1590

@sonnymilton

Description

@sonnymilton

Problem

When running Jupyter Server / JupyterLab behind a reverse proxy (Caddy, nginx, etc), the server typically binds to a local address such as 127.0.0.1:8888, while users access it via a stable URL like https://jupyter.local/.

Jupyter provides the ServerApp.custom_display_url option, which correctly prints the public URL (including the token) in the startup logs. However, when ServerApp.open_browser=True is enabled, Jupyter still opens the browser using the bind address (http://127.0.0.1:8888/...) instead of the public URL. This happens even though the correct public URL is already known and displayed.

As a result, users running Jupyter behind a reverse proxy with TLS and a custom hostname must either manually open the printed URL or implement wrapper scripts/workarounds to open the correct address.

Proposed Solution

When ServerApp.open_browser=True and ServerApp.custom_display_url is set, use custom_display_url as the base URL for opening the browser (including the correct path and token), instead of the local bind address.

Alternatively, introduce a dedicated configuration option (for example, ServerApp.public_url or ServerApp.browser_open_url) that explicitly controls which URL is used when opening the browser, while keeping custom_display_url as a display-only setting for logs.

Additional context

  • Typical setup: Jupyter Server / JupyterLab behind a reverse proxy (Caddy, Nginx, Traefik) with a local bind address (127.0.0.1:8888) and a public HTTPS URL.
  • custom_display_url already solves the problem of displaying the correct URL to the user, but open_browser does not currently respect it.
  • Current workarounds include disabling open_browser and opening the correct URL manually or via wrapper scripts (e.g. parsing the token from jupyter server list and calling xdg-open).
  • Supporting this behavior natively would improve the developer experience for local and self-hosted Jupyter setups using reverse proxies and TLS.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions