You're developing locally and need to test a webhook from Stripe. Or show a client your work-in-progress. Or test on your actual phone. Localhost tunneling gives your local server a public URL instantly - no deployment required.
Public URL in Seconds
Turn localhost:3000 into a public HTTPS URL. Share with anyone, anywhere - no configuration, no deployment, no firewall headaches.
How Tunneling Works
Tunneling creates a secure connection between your local machine and a public server, forwarding requests to your localhost:
Traffic flows from the internet through the tunnel service directly to your local development server
Key Features
Instant URLs
One command gives you a public URL. No signup required for basic use. Start sharing in under 10 seconds
HTTPS by Default
All tunnel URLs are HTTPS with valid certificates. Test OAuth callbacks, secure webhooks, and more
Webhook Inspection
See every request in real-time. Inspect headers, body, replay requests. Debug webhooks without console.log
Mobile Testing
Test on real devices without deploying. Open the tunnel URL on your phone and see your local app
Practical Examples
ngrok is the most popular tunneling tool. Here's how to expose your local server:
# Install ngrok (macOS)
brew install ngrok
# Or download from ngrok.com and add to PATH
# Expose your local server on port 3000
ngrok http 3000
# Output:
# Forwarding https://abc123.ngrok.io -> http://localhost:3000
#
# Web Interface http://127.0.0.1:4040 (inspect requests here!)
# Expose with custom subdomain (requires paid plan)
ngrok http 3000 --subdomain=myapp
# Expose with basic auth protection
ngrok http 3000 --basic-auth="user:password"
# Expose a specific host header (for virtual hosts)
ngrok http 3000 --host-header=myapp.local
Cloudflare Tunnel is a free alternative with no rate limits:
# Install cloudflared (macOS)
brew install cloudflared
# Quick tunnel - no account needed!
cloudflared tunnel --url http://localhost:3000
# Output:
# Your quick Tunnel has been created!
# https://random-words.trycloudflare.com
# For permanent tunnels, authenticate first
cloudflared tunnel login
# Create a named tunnel
cloudflared tunnel create my-tunnel
# Run the tunnel
cloudflared tunnel run --url http://localhost:3000 my-tunnel
Inspecting webhook requests with ngrok's web interface:
# 1. Start your local server
npm run dev # Running on localhost:3000
# 2. Start ngrok in another terminal
ngrok http 3000
# 3. Copy the HTTPS URL (e.g., https://abc123.ngrok.io)
# 4. Configure the webhook provider (Stripe, GitHub, etc.)
# Use: https://abc123.ngrok.io/webhooks/stripe
# 5. Open the inspection interface
# http://127.0.0.1:4040
# 6. Trigger a webhook event (e.g., make a test purchase)
# 7. See the request in the ngrok inspector:
# - Full request headers
# - Request body (JSON formatted)
# - Response from your server
# - Timing information
# 8. Click "Replay" to resend any request for debugging
Why Developers Love It
- ✓ Test Webhooks Locally - Stripe, GitHub, Twilio - receive webhooks on localhost without deploying
- ✓ Real Device Testing - Test your responsive design on actual phones, not emulators
- ✓ Client Demos - Show work-in-progress to clients without deploying to staging
- ✓ OAuth Callbacks - Test OAuth flows that require HTTPS redirect URLs
- ✓ Team Collaboration - Share your branch with teammates for testing before PR
- ✓ Debug External Services - See exactly what third-party services send you
Common Use Cases
| Use Case | Problem | Tunnel Solution |
|---|---|---|
| Webhook Testing | Services can't reach localhost | Public URL receives webhooks, forwards to local |
| Mobile Testing | Phone can't access laptop's localhost | Open tunnel URL on phone to test real device |
| OAuth Callbacks | OAuth requires HTTPS callback URL | Tunnel provides valid HTTPS certificate |
| Client Demos | Client can't see local work | Share tunnel URL - instant preview |
| QA Testing | QA team can't access dev machine | Share URL for pre-deployment testing |
| API Development | Frontend dev needs your local API | They hit tunnel URL, you see requests |
Cheatsheet
Quick reference for ngrok and Cloudflare Tunnel commands:
| Task | ngrok | Cloudflare Tunnel |
|---|---|---|
| Basic tunnel | ngrok http 3000 |
cloudflared tunnel --url localhost:3000 |
| HTTPS only | ngrok http https://localhost:3000 |
Default behavior |
| Custom subdomain | ngrok http 3000 --subdomain=myapp |
Requires DNS setup |
| Password protect | ngrok http 3000 --basic-auth="u:p" |
Use Cloudflare Access |
| TCP tunnel | ngrok tcp 22 |
cloudflared tunnel --url tcp://localhost:22 |
| Inspect UI | http://127.0.0.1:4040 |
Cloudflare dashboard |
| Pricing | Free tier + paid plans | Free (unlimited) |
Pro Tips
Replay Failed Webhooks
In ngrok's web interface at 127.0.0.1:4040, click "Replay" on any request. Perfect for debugging webhook handlers without triggering real events again.
Use ngrok.yml for Config
Create ~/.ngrok2/ngrok.yml to save your settings. Define tunnels, auth, regions - then just run ngrok start myapi.
Cloudflare for Free Production Tunnels
Unlike ngrok, Cloudflare tunnels are completely free with no rate limits. Great for self-hosting or exposing home lab services permanently.
Integrate with npm Scripts
Add to package.json: "tunnel": "ngrok http 3000". Run npm run tunnel alongside your dev server with concurrently.
Secure Sensitive Demos
Use --basic-auth to password-protect tunnel URLs. Share credentials only with intended viewers. Remember: anyone with the URL can access your local server!
Getting Started
-
1
Install Your Preferred Tool
ngrok:
brew install ngrokor download from ngrok.com. Cloudflare:brew install cloudflared -
2
Start Your Local Server
Run your development server as usual (e.g.,
npm run devon port 3000) -
3
Create the Tunnel
Run
ngrok http 3000orcloudflared tunnel --url localhost:3000in another terminal -
4
Share the Public URL
Copy the HTTPS URL from the output. Anyone can now access your local server through this URL!
Start Tunneling Today
Stop deploying just to test webhooks. Expose your localhost in seconds with ngrok or Cloudflare Tunnel.