Guide
Diagnosing ngrok Tunnels That Appear Up but Cannot Reach Your Local Service
A step‑by‑step diagnostic guide for when ngrok reports a healthy tunnel but your local service stays unreachable, covering port conflicts, firewall blocks, plan limits, region mismatches, auth tokens, and custom‑domain TLS.
Published by Tasadduq Burney
28 Sept 2025, 02:58 UTC
5 min12.2K views0

Recognizable Condition
You run ngrok http 8080 (or any TCP tunnel) and the console prints a public URL such as https://abcd1234.ngrok.io. The tunnel status shows online, yet opening that URL in a browser or with curl hangs, times out, or returns connection refused. No request appears in your local server logs.
Quick Cause‑and‑Symptom Reference
| Observed Symptom | Likely Root Cause |
|---|---|
ngrok logs Unable to bind to port or Port already in use | Another process already occupies the local port; ngrok cannot forward traffic. |
| Tunnel shows online, but local server logs stay empty | Traffic never reaches the host – firewall, antivirus, or routing block inbound packets on the ngrok agent port. |
| URL works from a different network (phone hotspot) but not from the same machine | Local host firewall or loopback routing prevents the ngrok client from delivering packets to the service. |
| Intermittent drops after a few requests | Free‑plan connection limit exceeded (40 connections/minute as of ngrok 3.x). |
Region mismatch warning in the console | Configured region (e.g., us) differs from the edge server actually assigned. |
| SSL certificate error when using a custom domain | Custom domain TLS requires a valid certificate; self‑signed or missing cert triggers browser errors. |
| Authentication failure after restart | Auth token expired, revoked, or not saved in ~/.config/ngrok/ngrok.yml. |
Ordered Diagnostic Checks
- Verify the local service is actually listening.
Run on the same host:
Expect a line showingss -ltn 'sport = :8080' # Linux netstat -an | findstr :8080 # Windows PowerShellLISTENon 0.0.0.0:8080 (or 127.0.0.1:8080). If missing, start the service first. - Confirm ngrok can bind to that port.
Start ngrok with verbose logging:
Watch forngrok http 8080 --log=stdout --log-level=debugUnable to bind to portlines. If present, identify the conflicting PID withlsof -i :8080(Linux/macOS) orGet-Process -Id (Get-NetTCPConnection -LocalPort 8080).OwningProcess(Windows) and stop it. - Check that traffic reaches the ngrok client.
In the ngrok web UI (defaulthttp://127.0.0.1:4040) inspect the Requests tab. If the request appears there but the local server logs nothing, the ngrok client received the HTTP request but failed to forward it locally. - Test from an external network.
Use a phone hotspot or a remote VM tocurl -v https://abcd1234.ngrok.io. Success from outside but failure locally points to a host‑side firewall or routing issue. - Inspect host firewall / antivirus.
Temporarily allow inbound on the ngrok agent port (default 4443 for the control channel, plus the random local port ngrok opens for the tunnel). Example forufw:
On Windows, add an inbound rule forsudo ufw allow 4443/tcp sudo ufw allow 8080/tcpngrok.exein Windows Defender Firewall. Retest step 3. - Validate plan limits and auth token.
Run:
It prints the account tier and token validity. If you seengrok config checkFree plan limit reachedin the console, upgrade or throttle requests. - Confirm region setting.
Explicitly set region to avoid mismatch:
Match the region shown in the dashboard (e.g.,ngrok http 8080 --region=usus,eu,ap). - Check custom‑domain TLS.
If using a custom domain, ensure the certificate and key are present in~/.config/ngrok/and referenced inngrok.yml:
Runtunnels: myapp: proto: http addr: 8080 hostname: app.example.com cert_path: /path/to/fullchain.pem key_path: /path/to/privkey.pemngrok start myappand verify no SSL errors in the browser.
Fixes Mapped to Findings
- Port conflict – Stop the conflicting process or change the local service port and update the ngrok command.
- Firewall blocking inbound – Add permanent allow rules for the ngrok agent and the local service port; avoid disabling the firewall entirely.
- Free‑plan throttling – Upgrade to a paid plan or implement client‑side back‑off to stay under 40 connections/minute.
- Region mismatch – Explicitly set
--regionor remove the region directive to let ngrok pick the nearest edge. - Expired auth token – Generate a new token from the ngrok dashboard and run
ngrok config add-authtoken <TOKEN>. - Custom‑domain TLS errors – Provide a valid, trusted certificate (Let’s Encrypt or a CA‑signed cert). Self‑signed certs only work if you also trust them on the client.
Escalation Criteria
Escalate to ngrok support (or your internal platform team) when:
- All firewall rules are correct, the local service logs show
LISTEN, yet the ngrok web UI still shows zero inbound requests after multiple external tests. - Authentication token is valid per
ngrok config checkbut the agent repeatedly logsauthentication failed. - Custom‑domain TLS is configured with a valid certificate, yet browsers report
ERR_CERT_AUTHORITY_INVALIDand the ngrok UI shows no certificate errors. - You suspect a platform‑level issue (e.g., ngrok edge outage) – check the ngrok status page before opening a ticket.
Practical Verification Checklist
- Start a minimal server:
python3 -m http.server 8080(ornpx serve -l 8080). - Run
ngrok http 8080 --log=stdoutand copy the HTTPS URL. - From a different network, run
curl -I https://<your‑id>.ngrok.io. Expect200 OKand aServer: SimpleHTTP/0.6 Python/3.xheader. - Confirm the request appears in the ngrok web UI (
http://127.0.0.1:4040) and in the Python server console. - If any step fails, refer to the diagnostic table above and apply the corresponding fix.
Limitations & Gotchas
- This guide assumes ngrok 3.x (released 2023). Older 2.x binaries emit different log lines and use a different configuration file location.
- Free‑plan limits are enforced at the edge; they manifest as silent drops, not as local errors.
- IPv6‑only local services need
ngrok http --host-header=rewrite 8080or an explicitaddr: '[::1]:8080'in the YAML. - Corporate proxies that terminate TLS before reaching ngrok can break the control channel; in that case use the
--proxyflag or run ngrok inside a VM with direct internet.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.