Skip to main content

What is Prime Tunnel?

Prime Tunnel creates secure, public URLs for services running on your local machine. You start a local server, create a tunnel, and get an HTTPS URL that anyone can access. Common use cases:
  • Expose a local development server to the internet
  • Receive webhooks from external services during development
  • Share a work-in-progress app with teammates
Hosted evaluations can use Prime Tunnel too. Launch the run with --allow-tunnel-access, then create the tunnel from inside the hosted sandbox using the same API or CLI flow described here. The flag only grants tunnel permissions to the temporary PRIME_API_KEY. See Hosted Evaluations.

Complete Example

Here’s a full working example: start a local HTTP server and expose it to the internet. 1. Start a local server
# Create a simple HTML file
echo '<h1>Hello from Prime Tunnel!</h1>' > index.html

# Start Python's built-in HTTP server on port 8000
python -m http.server 8000
2. Create a tunnel (in another terminal)
import asyncio
from prime_tunnel import Tunnel

async def main():
    tunnel = Tunnel(local_port=8000)
    await tunnel.start()

    print(f"Public URL: {tunnel.url}")
    print("Press Ctrl+C to stop")

    # Keep running until interrupted
    try:
        while True:
            await asyncio.sleep(1)
    except KeyboardInterrupt:
        pass
    finally:
        await tunnel.stop()

asyncio.run(main())

3. Access your server Open the printed URL (e.g., https://t-0-abc123def456.tunnel.pinfra.io) in any browser. Your local server is now accessible from anywhere.

Context Manager

For automatic cleanup, use the async context manager:
async with Tunnel(local_port=8000) as tunnel:
    print(f"URL: {tunnel.url}")
    # Tunnel is active here
# Tunnel automatically stopped

Tunnel Properties

tunnel = Tunnel(local_port=8000)
await tunnel.start()

tunnel.tunnel_id  # "t-0-abc123def456"
tunnel.url        # "https://t-0-abc123def456.tunnel.pinfra.io"

Protecting a Tunnel with Basic Auth

By default, anyone with the URL can reach your tunnel. To require credentials, provide a username when creating the tunnel — a strong password is auto-generated server-side and shown exactly once. All public traffic must then include HTTP basic auth; requests without valid credentials get a 401 Unauthorized.
tunnel = Tunnel(local_port=8000, http_user="alice")
await tunnel.start()

print(tunnel.url)
print(tunnel.http_password)  # auto-generated
The CLI prints the generated password when the tunnel starts:
Tunnel started successfully!
URL: https://t-0-abc123def456.tunnel.pinfra.io
Tunnel ID: t-0-abc123def456
Basic auth user: alice
Basic auth password: vBI6ioyAM3_X4KWaEug4TPSbzovK8eYb
Save this password - it is shown only once and cannot be retrieved later
Browsers prompt for the credentials automatically. For programmatic access, send the Authorization header:
curl -u alice:vBI6ioyAM3_X4KWaEug4TPSbzovK8eYb https://t-0-abc123def456.tunnel.pinfra.io

CLI Commands

# Start a tunnel
prime tunnel start --port 8000

# Start a tunnel protected by HTTP basic auth (password is auto-generated)
prime tunnel start --port 8000 --auth alice

# List active tunnels
prime tunnel list

# Stop a tunnel
prime tunnel stop t-0-abc123def456

Rate Limits

The tunnel API enforces per-user rate limits over a 60-second window.
EndpointMethodLimit
/api/v1/tunnelPOST600 requests / 60s
/api/v1/tunnelGET300 requests / 60s
/api/v1/tunnel/{id}GET300 requests / 60s per tunnel
/api/v1/tunnel/{id}DELETE100 requests / 60s
/api/v1/tunnelDELETE100 requests / 60s (bulk)
Requests over the limit return 429 Too Many Requests. There is also a per-account cap on the number of concurrent tunnels (tunnel_limit on the wallet) - delete unused tunnels before creating new ones.