What Is ngrok? Share Your Localhost With the Internet
ngrok gives your local app a public HTTPS URL by tunnelling traffic to your machine. What it's for (webhooks, demos, mobile testing), how to use it, the request inspector, free vs paid limits, security cautions, and alternatives like Cloudflare Tunnel.
When you run an app on your computer, it lives at http://localhost:3000 — reachable only from your own machine. (What is localhost?)
ngrok gives it a public HTTPS address that anyone (or any service) can reach. It does this with a tunnel: the ngrok program on your computer connects out to ngrok's servers, and requests to your public URL are forwarded down that connection to your local app.
Internet → https://abc123.ngrok.app → ngrok agent on your laptop → localhost:3000
What it's used for
- Testing webhooks. Stripe, GitHub, Twilio and others need a public URL to send events to. ngrok lets them reach the app on your laptop. (Test webhooks locally, What is a webhook?)
- Showing work to a client or teammate without deploying.
- Testing on a phone — open your local app on a real device.
- OAuth callbacks that require an HTTPS redirect URL. (Sign in with Google explained)
How to use it
Sign up at ngrok.com and install the agent (Homebrew, a download, or a package manager).
Connect your account once:
ngrok config add-authtoken YOUR_TOKENStart your app, then:
ngrok http 3000
ngrok shows a forwarding URL like https://abc123.ngrok-free.app. Open it from anywhere.
The request inspector
While ngrok runs, open http://127.0.0.1:4040. You'll see every request that came through — headers, body, response — and can replay any of them. For webhook debugging, this is gold: you can see exactly what Stripe sent and resend it after fixing your code.
Free vs paid
The free plan is enough for development, with limits that change from time to time — typically a random or single assigned domain, usage caps, and an interstitial warning page for browser visitors. Paid plans add custom domains, more endpoints and features like IP restrictions and authentication. Check ngrok's pricing for current limits.
Security cautions
- Your local app becomes public. Anyone with the URL can reach it — including any admin pages or debug endpoints. Don't expose something with real data or no login.
- Dev mode shows detailed errors that can reveal code and secrets. (npm run dev vs build)
- Stop the tunnel when you're done.
- Add ngrok's basic auth or OAuth options if you share a link more widely.
Some frameworks need a setting
Dev servers sometimes reject requests from unknown hostnames. Vite, for example, may need the ngrok host added to server.allowedHosts. If you see "Blocked request. This host is not allowed", that's why.
Alternatives
- Cloudflare Tunnel — free quick tunnels, and free custom domains if your DNS is on Cloudflare. (Cloudflare Tunnel explained)
- Stripe CLI —
stripe listen --forward-to localhost:3000/webhooksfor Stripe webhooks specifically, no tunnel needed. - VS Code port forwarding and Tailscale Funnel — other ways to share a local port. (What is Tailscale?)
- A real server — once others rely on it, it shouldn't depend on your laptop being open. (What is web hosting?)
The summary
- ngrok = a public HTTPS URL for an app on your machine.
- Brilliant for webhooks, demos and mobile testing; use the inspector at port 4040.
- Treat anything exposed as public; stop it when finished.
- For production, deploy properly.
EasySpawn gives your app a permanent public HTTPS address on a real server — and preview URLs for each branch — so you don't need a tunnel to show your work. See how it works or join the waitlist.
Related: Cloudflare Tunnel Explained · How to Test Webhooks Locally · What Is Localhost? · Preview Environments for Every Branch
Keep reading
What Is curl? A Beginner's Guide With Practical Examples
curl is a command-line tool for making web requests, installed on almost every computer. The commands you'll actually use — GET, POST JSON, headers, authentication, following redirects, downloading files, seeing response headers — and how to read API docs that use it.
"error: src refspec main does not match any": How to Fix It
Git can't push a branch called main because it doesn't exist locally — usually because there are no commits yet or the branch is called master. How to check which it is and fix it in one or two commands.