11 min read

How to Expose a Local API to the Internet for Development and Testing

Get a public HTTPS URL for your local API in under a minute. Test webhooks, share with teammates, and connect mobile apps without deploying anything.

🔌 Local API · Development · Testing · Webhooks · 2025

How to Expose a Local API to the Internet for Development and Testing

You built an API. It runs fine on localhost. Then a teammate needs to test it, a mobile app needs to reach it, or Stripe needs to send a webhook to it. Suddenly localhost is not enough. This guide covers every scenario where your local API needs a public URL and the fastest way to get one.

🪝 Webhook testing 📱 Mobile app development 👥 Team collaboration 🤖 AI agent backends

Why localhost Is Not Enough

When you start a development server, it listens on 127.0.0.1 or localhost. That address is private to your computer. Nothing outside your machine can reach it. This is fine for solo development, but it becomes a hard blocker the moment anyone or anything else needs to talk to your API.

🪝 Webhook providers Stripe, GitHub, Twilio, Slack and others send HTTP requests to a URL you provide. That URL must be reachable on the public internet.
📱 Mobile app testing A real device on mobile data or a different Wi-Fi network cannot reach your laptop's localhost. You need a public address.
👥 Team collaboration A teammate wants to test against your local API right now, without waiting for a deployment. A public URL makes this instant.
🤖 AI agent integration LangChain agents, n8n workflows, and MCP servers call external APIs over HTTP. Your local backend needs a reachable endpoint.
🔐 OAuth callbacks OAuth providers redirect users back to a callback URL after authentication. That URL must be on the public internet.
🧪 Integration testing Third-party services and CI systems that need to call your API during testing require a publicly reachable endpoint.
What about deploying to staging?

Deploying to a staging environment for every small change is slow and disconnects testing from the actual code you are writing. A tunnel gives you a public URL for the exact code running on your machine right now, with no deployment step.

How It Works

Localtonet creates an encrypted tunnel between your local machine and a relay server. Anyone who connects to the relay address is forwarded to your local API transparently. Your API never knows the difference. You get a public URL without touching your router, opening firewall ports, or having a public IP address.

Tunnel approach (Localtonet)
  • Works from any network including CGNAT
  • No router or firewall changes
  • HTTPS included automatically on HTTP tunnels
  • Live in under 60 seconds
  • No deployment, no staging server
Deploy to staging
  • Requires a full deployment cycle
  • Tests run against deployed code, not local code
  • Slower feedback loop
  • Costs money for every environment

Option A: HTTP Tunnel (for REST APIs and Web Services)

Use an HTTP tunnel when your API serves HTTP or HTTPS traffic. Localtonet provides a public URL and handles TLS automatically. Your local server can stay on plain HTTP.

1

Start your local API server

Make sure your API is running and note the port number. For example, an Express app on port 3000, a Flask app on port 5000, or a Laravel app on port 8000.

2

Create an HTTP tunnel in the dashboard

Log in to localtonet.com/dashboard, go to Tunnels → New Tunnel, select HTTP, set the local IP to 127.0.0.1 and the port to your API's port. Click Create. Localtonet generates a public HTTPS URL for you automatically.

3

Authenticate and start Localtonet

Run the Localtonet client on the same machine as your API using your AuthToken from Dashboard → My Tokens.

localtonet --authtoken <YOUR_TOKEN>

Your API is now reachable at the HTTPS URL shown in the dashboard. Test it immediately from another machine or browser:

# Replace with your actual tunnel URL
curl https://abc123.localto.net/api/users

# POST request
curl -X POST https://abc123.localto.net/api/orders \
  -H "Content-Type: application/json" \
  -d '{"item": "keyboard", "qty": 1}'

Option B: TCP Tunnel (for gRPC, WebSockets, or Non-HTTP APIs)

Use a TCP tunnel when your API uses a non-HTTP protocol such as gRPC, WebSockets over a raw TCP connection, database protocols, or any other TCP-based service. TCP tunnels forward raw traffic without protocol inspection.

1

Create a TCP tunnel

In the dashboard, go to Tunnels → New Tunnel, select TCP, enter your local port, and click Create. The relay address will look like example.localto.net:33XX.

2

Start the Localtonet client

Run Localtonet as described above. The tunnel activates and is ready to accept connections on the relay address.

3

Connect clients to the relay address

Configure your clients to connect to the relay host and port instead of localhost. All traffic is forwarded transparently to your local service.

Reserve a fixed port for stable endpoints

By default, TCP ports are assigned dynamically each time. If your clients or CI systems need a stable, unchanging address, reserve a port via Add-ons → Reserved Ports in the dashboard. Combine this with a custom domain for a permanent HTTPS endpoint.

Real-World Scenarios

🪝 Testing Stripe webhooks locally

Create an HTTP tunnel pointing to your local server's port. Copy the HTTPS tunnel URL. In the Stripe dashboard under Developers → Webhooks, add the tunnel URL as a new endpoint. Stripe delivers real payment events to your local code in real time. You see the full payload and can debug your handler without deploying anything.

📱 Mobile app hitting a local backend

Your iOS or Android app in development needs to call your local API. The phone is on mobile data or a different network. Point the app's API base URL to your Localtonet HTTP tunnel URL. The app now communicates with your laptop's server as if it were on the internet.

🔐 OAuth callback URL during development

OAuth providers like Google or GitHub redirect users to your callback URL after login. That URL must be on the public internet and registered in your OAuth app settings. Use your Localtonet tunnel URL as the registered callback and receive OAuth redirects directly in your local app.

👥 Sharing work-in-progress with a teammate

You are halfway through a feature and your backend colleague wants to test their frontend against your changes. Share your tunnel URL. They hit your local API from their machine in seconds. No branch deployment, no Docker setup, no waiting.

🤖 n8n or LangChain calling your local endpoint

You are building an AI agent or automation workflow that needs to call a custom API you are developing. The orchestration tool runs on a different machine or in the cloud. Give it your Localtonet HTTP tunnel URL and it talks to your local API on every workflow run.

🧪 Running integration tests from CI against local code

Your CI pipeline runs tests that call an API endpoint. Instead of deploying a test environment, start a Localtonet tunnel in your CI job and point the test runner at the tunnel URL. Tests run against the exact code in the current commit.

Quick Start by Framework

The steps are the same regardless of what your API is built with. Start the server, create the tunnel, use the URL.

Node.js / Express

// server.js
const express = require('express')
const app = express()
app.use(express.json())

app.get('/api/hello', (req, res) => {
  res.json({ message: 'Hello from local API' })
})

app.listen(3000, () => console.log('API running on http://localhost:3000'))
node server.js
# Now create an HTTP tunnel to port 3000 in the Localtonet dashboard

Python / FastAPI

# main.py
from fastapi import FastAPI

app = FastAPI()

@app.get("/api/hello")
def hello():
    return {"message": "Hello from local API"}
uvicorn main:app --port 8000
# Now create an HTTP tunnel to port 8000 in the Localtonet dashboard

Python / Flask

# app.py
from flask import Flask, jsonify

app = Flask(__name__)

@app.route('/api/hello')
def hello():
    return jsonify(message='Hello from local API')

if __name__ == '__main__':
    app.run(port=5000)
python app.py
# Now create an HTTP tunnel to port 5000 in the Localtonet dashboard

Go

// main.go
package main

import (
    "encoding/json"
    "net/http"
)

func helloHandler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(map[string]string{"message": "Hello from local API"})
}

func main() {
    http.HandleFunc("/api/hello", helloHandler)
    http.ListenAndServe(":8080", nil)
}
go run main.go
# Now create an HTTP tunnel to port 8080 in the Localtonet dashboard

Security During Development

✅ Use HTTP tunnels for automatic HTTPS

Localtonet HTTP tunnels come with a free Let's Encrypt TLS certificate. Your API is served over HTTPS automatically. No certificate setup, no self-signed cert warnings, no extra configuration on your local server.

🔐 Add SSO authentication to your tunnel

If your tunnel URL should only be accessible to specific people, enable Single Sign-On in the tunnel settings in the Localtonet dashboard. Anyone trying to reach your API through the tunnel must authenticate first using Google, GitHub, Microsoft, or GitLab.

⏱ Stop the tunnel when done

Development tunnels should not be left running indefinitely when you are not actively working. Stop the Localtonet client when you are done, or stop the tunnel from the dashboard. Your local API immediately becomes unreachable from the public internet.

🌍 Keep sensitive data out of dev APIs

Avoid using real production data in a locally exposed API. Use seeded test data or anonymized records. The tunnel itself is encrypted, but the endpoints on your local API may not have the same authentication and rate limiting as your production service.

Frequently Asked Questions

My API is on a different machine on the same network. Can I still tunnel it?

Yes. When creating the tunnel, set the local IP to the IP address of the machine running the API instead of 127.0.0.1. For example, 192.168.1.50 and port 3000. Localtonet will forward traffic to that address on your local network.

Will the tunnel URL change every time I restart Localtonet?

For HTTP tunnels, the subdomain can be made permanent by reserving it in the dashboard. For TCP tunnels, reserve a port via Add-ons → Reserved Ports to get a fixed address. You can also attach a custom domain for a completely stable HTTPS URL that never changes.

Does this work with APIs that use WebSockets?

Yes. Localtonet HTTP tunnels support WebSocket connections (WS and WSS). Clients can upgrade to WebSocket using your tunnel URL the same way they would on a regular HTTPS server.

Can I expose multiple API ports at the same time?

Yes. Create a separate tunnel for each port in the dashboard. Each tunnel gets its own public URL. Run a single Localtonet client instance and it handles all tunnels associated with your account simultaneously.

My API requires HTTPS but I'm running it on HTTP locally. Will it work?

Yes. Use an HTTP tunnel. Localtonet handles TLS termination at the relay and forwards plain HTTP to your local server. Clients see a valid HTTPS URL. Your local server does not need to handle TLS at all.

Does exposing my local API slow it down?

There is a small amount of added latency because requests travel through the Localtonet relay server. In practice this is unnoticeable for development and testing. For production traffic or latency-sensitive benchmarks, a direct connection is always faster.

Get a Public URL for Your Local API in Under a Minute

Create a free Localtonet account, start your API server, and open a tunnel. Webhooks, mobile apps, teammates and integrations can all reach your local API instantly.

Create Free Account →

Localtonet is a secure multi-protocol tunneling and proxy platform designed to expose localhost, devices, private services, and AI agents to the public internet supporting HTTP/HTTPS tunnels, TCP/UDP forwarding, mobile proxy infrastructure, file server publishing, latency-optimized game connectivity, and developer-ready AI agent endpoint exposure from a single unified control plane.

support