Picking free developer tunnels in 2026 is harder than “just use ngrok” suggests

I compared six ways developers expose localhost to the internet: Cloudflare Tunnel, ngrok, localhost.run, Pinggy, Tailscale Funnel, and VS Code port forwarding backed by Microsoft Dev Tunnels. The quick answers in forum threads mostly skip the part that actually bites you: how long the URL stays up, whether you can bind your own hostname, what sits between the public internet and your laptop, and how fast you hit free-tier walls.

My default for a durable free HTTP(S) preview, webhook endpoint, or internal tool you might leave running for months is Cloudflare named tunnels, not TryCloudflare quick shares. Cloudflare’s Zero Trust free plan is marketed as $0 forever for teams under 50 users, cloudflared runs outbound-only, and you can put real custom domains in front of local apps with Access policies, service tokens, IP rules, and the rest of the edge stack. The tradeoff is setup friction. You are wiring DNS and tunnel config, not pasting one command and moving on.

When I want the fastest polished first URL, I still reach for ngrok. It has the best CLI ergonomics in this set and serious edge auth through Traffic Policy. The free tier is tight: three online endpoints, three concurrent agents, 1 GB/month, 20,000 HTTP requests/month, and no custom domain. For a one-off demo that is often fine. For a webhook you forget about, you will hit a cap.

For near-zero friction on a locked-down machine, Pinggy and localhost.run win because they are SSH tunnels. Pinggy gives you 60-minute free sessions with random subdomains and unlimited transfer on the pricing page I read. localhost.run needs no signup for the basic path. Tailscale Funnel is elegant if you already live in Tailscale, but public hostnames are tailnet-name.ts.net only and the feature is still beta. VS Code port forwarding is what I use when the editor is the product and the share is temporary by design.

You cannot compare these on “does it work” alone

Every tool here can make localhost:3000 reachable from outside your network. The useful split is what happens after that.

FamilyToolsWhat they optimize for
Edge gatewayCloudflare Tunnel, ngrokA programmable policy layer in front of your local app
SSH tunnelerslocalhost.run, PinggyMinimal setup, works wherever SSH works
Identity / meshTailscale Funnel, Dev TunnelsSharing inside an identity or editor workflow

The questions I actually ask before picking one:

QuestionWhy it matters
PersistenceRandom URLs that rotate every reconnect are fine for a demo. Webhooks want stability.
Custom domain on freengrok free gets one permanent dev domain, not yours. Cloudflare named tunnels can bind a domain you control.
Access controlIs the tunnel URL itself a security boundary, or do you need gateway auth?
Metering unitHTTP requests, bandwidth, tunnel count, session length: vendors do not bill the same thing.

A sane workflow across all of them looks like this: run one app on one port, prefer outbound-only connectors over punching inbound firewall holes, add auth or policy at the edge when the tool supports it, and shut the tunnel down when you are done. Cloudflare Access is deny-by-default. ngrok can terminate OAuth and IP restrictions at the edge. VS Code keeps forwarded ports private unless you explicitly flip them public. Pinggy can do Basic Auth, bearer keys, and IP whitelisting. localhost.run is simpler and expects you to enforce auth in the app or treat the URL as a secret.

flowchart LR
    app[App on localhost:3000] --> choice[Exposure type]
    choice --> temp[Temporary share]
    choice --> persist[Persistent preview]
    temp --> random[Random tunnel URL]
    persist --> named[Named tunnel or custom domain]
    random --> policy[Add access control if available]
    named --> policy
    policy --> onePort[Expose one port only]
    onePort --> test[Webhook demo or mobile client]
    test --> shutdown[Rotate or shut down when done]

You will not get a perfect apples-to-apples table. Use the numbers below as directional, then test the path you actually need: SSE, long-lived WebSockets, TCP, or a quick HTTP POST from Stripe.

Free tiers at a glance

OptionFree limitsCustom domain on free?Security modelMain caveat
Cloudflare TunnelNamed tunnels: no published session, bandwidth, or request quotas in the docs I reviewed. Quick Tunnels: 200 in-flight requests, no SSE, dev/testing only, no SLA. Zero Trust free for teams under 50 users.Yes on named tunnels with a domain on Cloudflare (full or partial CNAME setup).Outbound-only cloudflared; Access deny-by-default; IdP, IP, country, service tokens, mTLS, device posture; inherits WAF and edge rules.Quick Tunnel is not the long-term answer. Named setup needs DNS plumbing.
ngrok3 online endpoints, 3 concurrent agents, no endpoint timeout, 1 GB/month, 20,000 HTTP req/month, 4,000 HTTP req/min, 5,000 TCP conn/month, 100 TCP conn/min.No. One permanent ngrok dev domain on free. Paid custom domains from $8/mo (Hobbyist) or BYO from $20/mo.Outbound agent; auto TLS; Traffic Policy with Basic Auth, OAuth/OIDC/JWT, IP restrictions.Free browser traffic hits an interstitial warning page. Quotas are the bottleneck, not uptime.
localhost.runForever free, no signup for basic use. Free domains rotate and change after a few hours. Speed-limited on free. Bandwidth/request quotas not publicly stated.No. Paid custom domain plan at $9/month billed annually.SSH tunnel; HTTPS endpoints; optional TLS passthrough so localhost.run does not decrypt. Minimal built-in visitor access controls.Tunnels can drop on flaky routes; docs recommend ServerAliveInterval and autossh.
PinggyHTTP(S), TCP, UDP, TLS. 60-minute tunnel timeout, random subdomains, unlimited data transfer per current pricing page. Request-rate and concurrent-tunnel caps not publicly stated.No. Pro plan required. Recent Pinggy post mentions paid plans around $2.50/month; re-check pricing before you buy.SSH remote forwarding; Basic Auth, bearer-key auth, IP whitelisting. Web Debugger can read traffic; TLS tunnels described as zero-trust mode.Free sessions expire. URL changes on reconnect.
Tailscale FunnelOn all plans including Personal ($0, up to 6 users, non-commercial per Tailscale). Funnel bandwidth limits exist but are not published. No session timeout published.No. tailnet-name.ts.net hostnames only.Encrypted relay; relay cannot decrypt proxied data per Tailscale. Policy controls who in the tailnet may enable Funnel. Limited anonymous visitor auth vs Cloudflare/ngrok.Still beta. Ports 443, 8443, 10000 only. TLS-only.
VS Code / Dev Tunnels5 GB/user/month, 10 tunnels/user, 10 ports/tunnel, 1,000 active connections/port, 1,500 HTTP req/min/port, 20 MB/s/tunnel, 16 MB max request body. Unused tunnels deleted after 30 days inactivity.No documented BYO domain. URLs under *.devtunnels.ms.Ports private by default in VS Code; GitHub account required. Public only if you change visibility. Microsoft/GitHub login, tokens, org scoping.Explicitly for development/testing. CLI is public preview, no SLA. Higher latency and occasional drops per Microsoft guidance.

Two things to keep in mind. Cloudflare publishes hard limits for Quick Tunnels but not for named tunnels in the material I reviewed, so “free forever” here means named tunnels plus Zero Trust, not cloudflared tunnel --url. And several SSH-based tools do not publish bandwidth or request caps for free tiers. I marked those as not publicly stated instead of guessing.

What the free tiers actually feel like in use

Cloudflare Tunnel: named path vs quick share

Cloudflare Tunnel is the option I would actually leave running. cloudflared opens outbound connections to Cloudflare over HTTP/2 or QUIC. Cloudflare documents four connections across multiple data centers per running tunnel for baseline HA. You can front the hostname with Access and deny-by-default policies that check identity, groups, IP ranges, country, service tokens, and client certificates.

The mistake I see constantly is treating TryCloudflare as the product. Quick Tunnels are explicitly dev/testing only: 200 in-flight requests, no Server-Sent Events, no SLA, no custom domain. Fine for “show my cofounder this branch.” Wrong for a webhook you register with a payment provider and forget about. The durable free path is a named tunnel, DNS routed through Cloudflare, and optionally Access in front.

Setup is more work than ngrok. You are creating a tunnel, routing DNS, and often managing a config.yml or a system service. In return you get custom domains without paying for the tunnel itself and more policy control than anything else on this list at $0.

ngrok: best DX, tightest free economics

ngrok is still the tool I recommend when someone says “I need a public URL in the next sixty seconds.” Authtoken, ngrok http 3000, done. No endpoint timeout on free. Traffic Policy can enforce Basic Auth, OAuth/OIDC, JWT validation, and IP restrictions at the edge. Global PoPs and latency-aware routing are documented properly.

The free tier runs out of runway faster than newcomers expect. Three endpoints, three agents, 1 GB/month, and 20,000 HTTP requests/month add up when you point a real webhook at it or leave a tunnel up through a sprint. Custom domains are paid. Free HTTP/S endpoints also show an interstitial warning page to visitors, which is awkward for client demos even when the tunnel itself works.

ngrok is excellent technology with a free tier sized for light use, not for “my side project’s public ingress layer.”

localhost.run: SSH and nothing else

localhost.run is the minimalist pick. If ssh works, you can run ssh -R 80:localhost:3000 localhost.run and get an HTTPS endpoint. No client install beyond what you already have. No account for the basic free path.

That simplicity has a ceiling. Free hostnames rotate and are speed-limited. The FAQ is honest that tunnels can drop when internet routing gets weird; keepalives and autossh are the documented fix. There is no Cloudflare Access or ngrok Traffic Policy equivalent. You rely on app auth, network obscurity, or accepting that anyone with the URL can hit your local server. The paid custom-domain plan at $9/month annually is reasonable if you want a stable hostname without leaving the SSH model.

Pinggy: generous transfer, short sessions

Pinggy is the ngrok alternative I reach for when I want SSH simplicity but also TCP, UDP, or TLS forwarding. The free plan gives 60-minute sessions, random subdomains, and unlimited data transfer on the pricing page I read. One command through free.pinggy.io and you are live.

The trust model deserves a conscious choice. Pinggy’s docs say the Web Debugger can read traffic, and they recommend TLS tunnels when you want a mode where Pinggy cannot read your data. That is not a dealbreaker for local API testing. It matters if you are tunneling something sensitive and treating the tunnel vendor as out of scope for compliance.

For persistent branded ingress, you will want Pro. Free is for “I need a URL now,” not “this is my staging environment for the quarter.”

Tailscale Funnel: great inside the tailnet, awkward for public branding

Tailscale Funnel makes sense when you already standardized on Tailscale for private access and want to expose one local HTTPS service to the public internet without opening inbound ports. tailscale funnel 3000 is clean. Traffic is relayed, encrypted, and Tailscale says the relay cannot decrypt the proxied data.

For public dev previews on your own domain, it is a weaker fit today. Funnel is still beta. Hostnames must live on your ts.net domain. Only ports 443, 8443, and 10000. Bandwidth limits exist and are not configurable or published. Custom domains remain a frequent community request, not a documented feature. If myapp.tailnet-name.ts.net is acceptable and you are already paying the Tailscale mental overhead, Funnel is elegant. If you need preview.mycompany.com on free, look at Cloudflare instead.

VS Code port forwarding: private by default, scoped to dev

VS Code port forwarding uses Microsoft Dev Tunnels. Forwarded ports start private. Making them public is a deliberate action. That default is the strongest privacy posture in this list after Cloudflare Access, and it matches how I actually work: share a port with someone debugging the same branch, then close it.

Microsoft is explicit that Dev Tunnels are for ad hoc development and testing. The CLI is public preview with no SLA. Official agent guidance warns about higher latency than cloud-hosted services and possible connection drops. Community threads mention 60-second timeouts in some cases. The published quotas (5 GB/user/month, 10 tunnels, and the per-port connection and request limits in the table above) are generous for demos. They are not a substitute for production ingress.

I use this when the debugging session is the point. I do not use it when I need a webhook endpoint that survives laptop sleep, CI, and three weeks of forgetfulness.

Why Cloudflare named tunnels win the free-forever argument

The combination that is hard to beat at $0: persistent named tunnels, real custom-domain support, serious zero-trust controls, and no published metered usage cap for named tunnels in the docs I reviewed. Cloudflare’s free Zero Trust plan covers teams under 50 users, and a published app can sit behind Access with deny-by-default enforcement plus normal edge protections.

Architecturally, cloudflared is more than a disposable reverse tunnel. Four outbound connections across multiple data centers is a real HA baseline. Once configured, the control-plane maturity is closer to production ingress than “SSH trick with a random subdomain.”

The counterpoints are real too.

Onboarding friction. ngrok, Pinggy, localhost.run, and VS Code all get you to a first successful URL faster. Cloudflare wants a named tunnel and usually some DNS work. TryCloudflare is fast but explicitly not durable.

Centralization. Fronting your laptop with Cloudflare means Cloudflare’s edge is now in your dependency graph. That is usually a good trade. It is still a trade, and large shared-edge outages affect everyone on the platform.

Protocol shape. Cloudflare Tunnel is strongest for HTTP(S) and web-adjacent workflows. If you live in Tailscale ACLs and MagicDNS already, Serve/Funnel may fit your brain better even without custom domains. If the tunnel only exists inside your editor session, Dev Tunnels may be less overhead than standing up Zero Trust.

For webhooks, mobile client testing against a local API, and staging previews on a hostname you control without paying for the tunnel line item, Cloudflare named tunnels are the pick I keep coming back to.

Setup snippets

Minimal commands from official docs. Adjust ports and hostnames to your app.

ngrok

ngrok config add-authtoken $NGROK_AUTHTOKEN
ngrok http 3000

# Paid custom domain example
ngrok http 3000 --url https://app.example.com

Cloudflare Tunnel

# Quick Tunnel (dev/testing only)
cloudflared tunnel --url http://localhost:3000

# Named tunnel sketch
cloudflared tunnel create dev
cloudflared tunnel route dns dev app.example.com
# then run the tunnel per your config or service setup

localhost.run

ssh -R 80:localhost:3000 localhost.run

# Paid custom domain example
ssh -R app.example.com:80:localhost:3000 plan@localhost.run

Pinggy

ssh -p 443 -R0:localhost:3000 free.pinggy.io

Tailscale Funnel

tailscale funnel 3000

VS Code / Dev Tunnels

devtunnel user login
devtunnel host -p 3000
# explicit public access:
devtunnel host -p 3000 --allow-anonymous

Security habits that apply everywhere: start private or authenticated and only go public when the integration requires it. Forward one service on one port, not your whole machine. Use end-to-end TLS for anything sensitive. If the tunnel has no gateway auth, your application must enforce its own. Close or rotate tunnels when the sharing window ends.

What I would pick

flowchart TD
    start[Need to expose localhost] --> domainQ{Need your own domain on free?}
    domainQ -->|Yes| cloudflare[Cloudflare named tunnel]
    domainQ -->|No| speedQ{Need a URL in under a minute?}
    speedQ -->|Yes| fastPick{SSH available?}
    fastPick -->|Yes| pinggy[Pinggy or localhost.run]
    fastPick -->|No| ngrok[ngrok]
    speedQ -->|No| tailscaleQ{Already on Tailscale and ts.net OK?}
    tailscaleQ -->|Yes| funnel[Tailscale Funnel]
    tailscaleQ -->|No| editorQ{Sharing from VS Code session?}
    editorQ -->|Yes| devtunnels[VS Code Dev Tunnels]
    editorQ -->|No| cloudflare

Solo dev testing webhooks or mobile clients against a local API: Cloudflare named tunnel if you can spend twenty minutes on DNS once. ngrok if you need it working before the coffee cools and the traffic will stay light.

Team preview environments on a real hostname without a tunnel line item: Cloudflare named tunnels plus Access. ngrok paid tiers if you want ngrok’s Traffic Policy UX and can accept the caps or the bill.

Locked-down laptop where installing cloudflared is annoying but SSH works: localhost.run for the quickest throwaway share, Pinggy when you need TCP/UDP/TLS or auth knobs on the tunnel.

Editor-centric pair debugging: VS Code port forwarding. Keep ports private unless the other person truly needs a public URL.

For a bootstrapped web app I would stand up a Cloudflare named tunnel, put Access or service-token auth in front of anything that is not a public webhook, and keep ngrok or Pinggy installed for the days I just need to paste a URL into a Slack thread.

Gaps in the public docs

Cloudflare named tunnels, localhost.run free bandwidth, Pinggy free request quotas, and Tailscale Funnel bandwidth either have no public number or only a qualitative description in the official material I reviewed. I left those fields blank instead of inventing limits.

Nobody publishes repeatable tunnel benchmarks I would trust for ranking. The performance claims that hold up best are architectural: nearest-edge routing, relay vs direct paths, published quotas, and official latency caveats. Community threads about timeouts and drops are warning signs, not a scorecard.

Pinggy’s Pro pricing shifted between the pricing page and a recent blog post when I checked. Treat dollar amounts as directional and confirm inside the product before you budget.

Sources

Cloudflare Tunnel

Cloudflare Tunnel overview
Create a remote tunnel
TryCloudflare (Quick Tunnels)
Cloudflare Zero Trust pricing
Cloudflare Access

ngrok

ngrok pricing
ngrok Traffic Policy
ngrok documentation

localhost.run

localhost.run
localhost.run docs
Custom domains

Pinggy

Pinggy
Pinggy documentation
Pinggy usage (auth and tunnel options)
Key authentication

Tailscale

Tailscale Funnel
Tailscale pricing

Microsoft Dev Tunnels

Dev Tunnels overview
Dev Tunnels limits and quotas
VS Code port forwarding