What Is ngrok?
A lot of development happens on a laptop: a local web server, a webhook endpoint, an API you’re testing, or a demo you want to show to someone. The problem is that “localhost” is private. ngrok solves that by giving your local app a temporary public URL that forwards traffic straight to your machine.
This article explains what ngrok is, why you might need it, and how to use it safely and effectively.
What ngrok is (in plain terms)
ngrok is a tunneling tool. It creates a secure tunnel from the public internet to a service running on your local computer. When you start ngrok, it connects to ngrok’s servers and assigns you a public address (usually HTTPS). Requests to that address are routed through the tunnel to your local port.
A simple example:
- You run a local server on
http://localhost:3000 - You start ngrok and ask it to tunnel port
3000 - ngrok gives you a public URL like
https://abc123.ngrok-free.app - Anyone who visits that URL hits your local server, as if it were hosted online
This is useful for development and testing because it makes local services reachable without deploying them.
Why localhost can’t receive external traffic
Most home and office networks sit behind a router with Network Address Translation (NAT). Your computer has a private IP that the public internet can’t reach directly. Even if your router has a public IP, incoming traffic is blocked unless you configure port forwarding, firewall rules, and sometimes dynamic DNS.
ngrok avoids all of that because the connection is initiated from your machine outward. Your computer establishes an outbound session to ngrok, and ngrok uses that session to relay inbound requests back to you.
Why you might need ngrok
1) Testing webhooks locally
Webhooks require a public URL. Payment processors, chat tools, shipping services, auth providers, and many other platforms send POST requests to your endpoint. If your endpoint is running only on localhost, the service can’t reach it.
With ngrok:
- You set the webhook URL to the ngrok HTTPS address
- Requests arrive at ngrok
- ngrok forwards them to your local route (for example,
/webhooks/payment)
This shortens feedback loops a lot.
2) Sharing a local demo quickly
Sometimes you want a teammate or client to see your work without deploying. ngrok lets you share a URL that points to your local dev server. For quick UI reviews, proof-of-concepts, or debugging sessions, this is convenient.
3) Mobile device testing
Testing on a real phone can be annoying if your dev server is only bound to localhost. A public ngrok URL works on the phone over cellular or Wi‑Fi, with no local network setup required.
4) Testing OAuth and login redirect URLs
OAuth flows often require redirect URLs that are HTTPS and publicly reachable. ngrok provides HTTPS endpoints, making it easy to test callbacks locally.
5) Debugging external integrations
When an external system fails to call your service, you want visibility into the exact request it is sending. ngrok includes an inspection interface that shows requests, headers, payloads, and responses. That makes it easier to spot signature issues, wrong content types, redirects, and other subtle bugs.
How ngrok works behind the scenes
A simplified flow:
- You run
ngrok http 3000 - ngrok opens an outbound secure connection to its cloud service
- ngrok allocates a public URL and binds it to your session
- A client sends a request to that public URL
- ngrok forwards the request across the tunnel to
localhost:3000 - Your local server responds
- ngrok forwards the response back to the client
This forwarding is transparent to your app. Your local server behaves normally; it just receives traffic that appears to originate from ngrok.
Installing ngrok
ngrok is available for major operating systems. After installing, you typically authenticate once so your tunnels are tied to your account.
Common setup flow:
- Install the ngrok binary (or package)
- Sign up for an account (if required for your usage)
- Add your auth token locally (one-time step)
Once authenticated, you can start tunnels from the command line.
Basic usage: expose a local HTTP server
Let’s say your app runs on port 3000.
-
Start your local server:
- Example:
npm run dev(or your framework’s equivalent)
- Example:
-
Start ngrok:
Bash -
Copy the public URL ngrok prints (prefer the HTTPS one)
-
Visit the public URL in your browser
- You should see your local app
What you’ll see in the terminal
ngrok typically shows:
- Forwarding URL(s) (HTTP and HTTPS)
- Connection status
- Request log (basic info like method and path)
Using the request inspection interface
ngrok provides a local web UI (often on a port like 4040) where you can inspect traffic.
Typical workflow:
- Trigger the webhook or open the public URL
- Open the inspector in your browser
- Click a request to see:
- Headers
- Body
- Response status and content
- Timing details
This is one of the best parts of ngrok when troubleshooting webhooks.
Exposing a specific path or host settings
ngrok tunnels a port, not a single route, but you can still control behavior:
- Your app can route incoming requests by path, such as
/api,/webhook,/health - Some setups require correct host headers or trusted proxy settings because traffic is coming through ngrok
Many web frameworks need a “trust proxy” setting so they treat forwarded headers properly (for example, to detect the original protocol as HTTPS). If your app generates absolute URLs or uses secure cookies, you may need to configure this.
TCP tunnels (when HTTP isn’t enough)
While HTTP(S) is the most common use, ngrok can also tunnel raw TCP for certain protocols. This can help with:
- Database access for debugging (use with caution)
- Custom TCP services
The commands differ from HTTP mode, and you should be extra careful with exposure and access controls.
Practical examples you can try
Example 1: Local webhook receiver
- Run a small server that prints incoming requests (Node, Python, etc.)
- Start ngrok on that port
- Paste the ngrok URL into the webhook provider’s dashboard
- Trigger an event
- Inspect the request in ngrok’s UI
Example 2: Share a frontend running locally
- Start your frontend dev server
- Start ngrok
- Send the URL to someone for a short review session
Security and safety tips
Exposing a local service to the public internet comes with risk. A few good habits:
- Tunnel only what you need, and stop ngrok when finished
- Avoid exposing admin panels, databases, or internal tools
- Add authentication in your app for sensitive routes
- Validate webhook signatures and reject unsigned requests
- Watch logs for unexpected traffic
- Use allowlists or access controls if your plan supports them
- Treat the public URL like a temporary doorway into your machine
Common issues and quick fixes
“My app works locally but fails through ngrok”
Possible causes:
- App is bound to
127.0.0.1only and not accepting forwarded traffic properly (less common for standard setups) - Incorrect base URL generation (app thinks it’s HTTP when it’s actually HTTPS)
- Secure cookies not set due to proxy settings
- CORS rules blocking requests from the ngrok domain
“Webhook provider says my endpoint is invalid”
Check:
- You used the HTTPS ngrok URL
- Your route exists and returns a 2xx status quickly
- Your server accepts the provider’s content type (often JSON)
- You’re not redirecting to another URL unexpectedly
When to use ngrok (and when not to)
ngrok is great for development, debugging, short-lived demos, and integration testing. For production services, a proper deployment with stable domains, hardened security, and monitoring is a better fit. ngrok can still play a role in staging or internal testing, but it’s usually not the final hosting solution.
ngrok gives you a simple way to expose a local service to the public internet, with HTTPS, a shareable URL, and tools to inspect requests. If you work with webhooks, OAuth callbacks, mobile testing, or quick demos, it can save a lot of time and remove network setup headaches. Use it intentionally, keep tunnels temporary, and treat the public URL as a real entry point that deserves the same caution as any internet-facing endpoint.












