Skip to content

Browser

The @pydantic/logfire-browser NPM package wraps OpenTelemetry browser tracing with sensible defaults and provides a simple API for creating spans and reporting exceptions.

Simple Usage

import { getWebAutoInstrumentations } from "@opentelemetry/auto-instrumentations-web";
import * as logfire from '@pydantic/logfire-browser';

// Set the path to your backend proxy endpoint
// For example, if using the Python `logfire_proxy` handler hosted on the same domain:
const url = new URL(window.location.href);
url.pathname = "/logfire-proxy/v1/traces";

logfire.configure({
  traceUrl: url.toString(),
  serviceName: 'my-service',
  serviceVersion: '0.1.0',
  // The instrumentations to use
  // https://www.npmjs.com/package/@opentelemetry/auto-instrumentations-web - for more options and configuration
  instrumentations:[
    getWebAutoInstrumentations()
  ],
  // This outputs details about the generated spans in the browser console, use only in development and for troubleshooting.
  diagLogLevel: logfire.DiagLogLevel.ALL
})

Note that if you’re using an SSR/SSG framework, you should ensure that the code above runs only in the browser runtime. A dedicated example for Next.js is available.

Proxying Browser Telemetry

If you use a Python backend, logfire provide experimental tools in the logfire.experimental.forwarding module to easily create this proxy.

FastAPI

For FastAPI, logfire provide a built-in logfire_proxy handler that limits request body size (default 50MB) by reading in chunks to avoid loading oversized payloads into memory.

main.py
from fastapi import FastAPI, Request

import logfire
from logfire.experimental.forwarding import logfire_proxy

logfire.configure()
app = FastAPI()


# Mount the proxy handler
# Note: {path:path} is strictly required to capture the OTLP route (e.g., /v1/traces)
@app.post('/logfire-proxy/{path:path}')
async def proxy_browser_telemetry(request: Request):
    return await logfire_proxy(request)

By default, this endpoint is unauthenticated and accepts payloads up to 50MB. In production, you should protect it using FastAPI dependencies to prevent abuse:

from fastapi import Depends, FastAPI, Request

import logfire
from logfire.experimental.forwarding import logfire_proxy

logfire.configure()
app = FastAPI()


async def verify_user_session():
    # Implement your authentication/rate-limiting logic here
    pass


@app.post('/logfire-proxy/{path:path}', dependencies=[Depends(verify_user_session)])
async def proxy_browser_telemetry_secure(request: Request):
    return await logfire_proxy(request)

Starlette

For Starlette, you can mount the logfire_proxy handler directly as a route.

main.py
from starlette.applications import Starlette
from starlette.routing import Route

import logfire
from logfire.experimental.forwarding import logfire_proxy

logfire.configure()

app = Starlette(
    routes=[
        # Note: {path:path} is strictly required to capture the OTLP route (e.g., /v1/traces)
        Route('/logfire-proxy/{path:path}', logfire_proxy, methods=['POST'])
    ]
)

Generic Python Frameworks

If you are using another web framework (such as Django, Flask, Litestar, or a custom HTTP server), you can use the underlying forward_export_request function directly.

You simply extract the path, headers, and body from your framework’s request object, pass them to forward_export_request as keyword arguments, and return the resulting status code, headers, and content.

main.py
import logfire
from logfire.experimental.forwarding import forward_export_request

logfire.configure()

class CustomFrameworkResponse:
    """Replace this with your framework's actual Response class."""
    def __init__(self, content: bytes, status_code: int, headers: dict[str, str]):
        pass

# Example generic route handler:
def my_custom_proxy_route(request):

    # 1. Extract data from your framework's request object
    path = request.path      # e.g. "/v1/traces"
    headers = request.headers
    body = request.read()

    # 2. Forward the request to Logfire
    response = forward_export_request(
        path=path,
        headers=headers,
        body=body
    )

    # 3. Return the Logfire response to the browser
    return CustomFrameworkResponse(
        content=response.content,
        status_code=response.status_code,
        headers=response.headers
    )