Skip to main content
← All Comparisons

Cloudflare Tunnel vs ngrok vs Tailscale Funnel

Which one fits which job, and when qURL™ fits better because nobody else should reach the app.

All three give your app a public address. Cloudflare Tunnel puts it on your own domain and can add Cloudflare Access in front; ngrok gives you a free dev domain once you add an authtoken; Tailscale Funnel publishes a ts.net name anyone can reach. If one person or agent needs one private app for a while, qURL sends them an expiring link and gives the app no public address.

Facts checked October 1, 2026 against each vendor’s documentation or our tests. Download the data

Which one to use

Which tool to use for each job, and why
If you needUseWhy
Webhooks, or a public API anyone can callngrokA stable public dev domain on the free plan, and Traffic Policy for OAuth, OIDC, or IP rules when you need them.
A lasting hostname on your own domain, behind your company sign-inCloudflare Tunnel with Cloudflare AccessThe hostname lives on your Cloudflare domain, and Access policies decide who gets through.
A public demo from a device already on your tailnetTailscale FunnelOne command on a tailnet device, on ports 443, 8443, or 10000. Anyone on the internet can open it.
Teammates who are already on your tailnetTailscale Serve, not FunnelServe keeps access private to authorized Tailscale users and passes viewer identity to the app.
Give an agent access to a private app that needs an Authorization headerqURLqURL can add the app’s credential to requests, so you do not need to build a separate proxy. Requires an advanced CLI setup; see the reference.
One person or agent needs one private app, for a whileqURLNo account and no public address. Each recipient gets a link that is single-use by default and expires within 24 hours.

The command to a first shareable URL

What each tool needs installed and the commands to a first shareable URL
ToolWhat you installCommand to the first shareable URL
Cloudflare Tunnel (named)cloudflaredCreate the tunnel in the dashboard, run the cloudflared install command it shows, then add a published application route
ngrok (free plan)ngrok agentngrok config add-authtoken <TOKEN> ngrok http 8080
Tailscale FunnelTailscale client 1.38.3 or later (an open-source variant on macOS)tailscale funnel 3000
qURL CLIqurl CLI (Homebrew or release download)qurl publish http://127.0.0.1:3000 qurl share <CRID>

All four, side by side

Cloudflare Tunnel, ngrok, Tailscale Funnel, and the qURL CLI compared, with the source for each value
QuestionCloudflare Tunnel (named)ngrok (free plan)Tailscale FunnelqURL CLI
Account needed before the first URLYes: account plus a domain on Cloudflare developers.cloudflare.comYes: account and authtoken ngrok.comYes: a tailnet with MagicDNS, HTTPS certificates, and the funnel node attribute tailscale.comNo. The first publish creates the device identity our test
What the URL looks likeStable hostname on your own domain developers.cloudflare.comOne assigned dev domain per account (ngrok-free.app / ngrok-free.dev), stable ngrok.comStable machine-name.tailnet-name.ts.net; machine names are published in Certificate Transparency logs tailscale.comA qurl.link access link per recipient; the app answers at r_<id>.qurl.site, a name absent from Certificate Transparency logs our test
Who can reach itPublic unless you add a Cloudflare Access application developers.cloudflare.comPublic: anyone with the URL ngrok.comPublic: anyone on the internet tailscale.comNo one until a link is opened; then the opener’s public IP for that session, including other devices behind that IP layerv.ai
Warning page shown to visitorsNot documented developers.cloudflare.comYes, on free-plan browser traffic (ERR_NGROK_6024) ngrok.comNot documented tailscale.comNone our test
Visitor access controlCloudflare Access policies; service tokens for machines developers.cloudflare.comTraffic Policy: OAuth, OIDC, basic auth, IP restrictions (free plan: 3 OAuth/OIDC users a month) ngrok.comNone on Funnel traffic; Funnel requests carry no Tailscale identity headers tailscale.comSingle-use access link by default; link and session lifetimes. IP allow and deny lists and other rules can gate links through the API, not the CLI layerv.ai
Link expiryNo per-link expiry; Access session settings apply developers.cloudflare.comNo built-in expiry; free endpoints have no timeout and stay up while the agent runs ngrok.comNo; runs until you turn it off tailscale.comYes. qurl share returned a 24-hour link in our no-account test; no-account links are capped at 24 hours our test
Single-use linksNot documented developers.cloudflare.comNot documented ngrok.comNo tailscale.comYes, the default for qurl share our test
ProtocolsHTTP(S); TCP, SSH, RDP, SMB with cloudflared on the client developers.cloudflare.comHTTP(S); TCP after card verification ngrok.comHTTPS proxy, TCP, TLS-terminated TCP; ports 443, 8443, and 10000 only tailscale.comHTTP(S), WebSocket, SSE; no raw TCP our test
Free-tier limitsAvailable on all plans; 1,000 tunnels per account, 25 replicas per tunnel developers.cloudflare.com3 endpoints, 1 GB/month out, 20,000 HTTP requests/month, 4,000 requests/min ngrok.comAvailable on all plans; non-configurable bandwidth limits, not published; beta tailscale.comWithout an account: up to 3 active resources, with links that last up to 24 hours github.com

What they have in common, and where qURL differs

Cloudflare Tunnel, ngrok, and Tailscale Funnel all answer the same question: how do I give this app an address other people can reach? Each puts the app on a public name, then leaves it to you to decide who gets through: Cloudflare Access policies, ngrok Traffic Policy, or, for Funnel, the app’s own sign-in.

qURL answers a narrower question: how do I let this one person or agent in, for a while? The app gets no public address. qurl publish registers it, and qurl share prints a link for one recipient that is single-use by default and expires within 24 hours. It suits a client preview, a check on your phone, or an agent that needs a private target. It does not suit webhooks, a public API, or raw TCP, which is where the three tunnels win.

Frequently Asked Questions

Which of the three is private by default?

None. A Cloudflare Tunnel hostname is public unless you add a Cloudflare Access application, an ngrok URL is public unless you add a Traffic Policy, and Tailscale Funnel is public to anyone, with no access control on Funnel traffic. Tailscale Serve is private, but viewers need a Tailscale account and client. With qurl 3.4.1 or later, a plain publish makes the app private: it opens only for the publisher’s devices and the people and devices the publisher allowed. A single-use access link is one way to let a recipient in.

Do any of them work without an account?

No. Cloudflare Tunnel needs a Cloudflare account and a domain on Cloudflare, ngrok needs an account and authtoken, and Funnel needs a tailnet. Cloudflare quick tunnels on trycloudflare.com skip the account, and so does the qURL CLI.

Can I give someone a link that expires or works once?

Not with these three. ngrok endpoints have no built-in expiry and stay up while the agent runs, Cloudflare Tunnel has no per-link expiry (Access session settings apply), and Funnel runs until you turn it off. None of them documents single-use links. With no flags, qurl share prints a link that can be opened once and expires within 24 hours.

Which one gives me a stable URL?

All three. Cloudflare Tunnel gives you a stable hostname on your own domain, the ngrok free plan gives each account one stable dev domain on ngrok-free.app or ngrok-free.dev, and Funnel uses machine-name.tailnet-name.ts.net, a name that is published in Certificate Transparency logs. qURL gives each recipient their own access link instead of one shared URL.

What does each one cost to start?

Cloudflare Tunnel is available on all Cloudflare plans. The ngrok free plan includes 3 endpoints, 1 GB a month of outbound data, and 20,000 HTTP requests a month. Funnel is available on all Tailscale plans with bandwidth limits Tailscale does not publish, and it is in beta. The qURL CLI without an account allows up to 3 active resources, with links that last up to 24 hours.

Who can open a qURL link?

Whoever holds it, once: with no flags, qurl share prints a single-use link. Opening it admits the network address it was opened from for the session, which lasts 1 hour by default for an app published from the CLI. Other devices on the same public IP address, such as an office or café network, can reach the app until the session ends, so keep your app’s own sign-in for anything sensitive. By default a link admits whoever opens it; access rules set through the API, such as IP allow and deny lists, can restrict that.

Share one app without a public address

Install the qURL CLI, then publish the app you have running. No sign-up.

Install the CLI ↗

New to qURL? Start at qurl.link

Contact sales

Contact our team for enterprise deployments.

Enterprise starts with a scoped, paid pilot on one application, typically 60 to 90 days, credited in full toward year one if you convert within 60 days. Then an annual package sized to what you protect. Not per seat.