Tunnelmole vs ngrok: A Native npm Alternative for Node.js Developers

 

Tunnelmole vs ngrok: A Native npm Alternative for Node.js Developers

Every developer running a local server eventually hits the same wall: the app works fine on localhost:3000, but a webhook provider, a physical phone, or a client on the other side of the world can't reach it. For years, ngrok has been the default fix. Tunnelmole is a newer, TypeScript-native option that's picked up traction specifically among Node.js and JavaScript developers who'd rather not leave the npm ecosystem to get a public URL.

This piece compares the two head-to-head: installation friction, licensing, self-hosting, and the parts of Tunnelmole's own documentation that are worth reading before you point production-adjacent traffic through it.

Why Tunneling Tools Exist

Your router and OS firewall block inbound traffic to your machine by default — that's a feature, not a bug. But it creates real friction during development:

  • Webhooks: Stripe, Twilio, GitHub, and Discord need a public URL to POST to. They can't reach localhost:3000.
  • Mobile and cross-device testing: phones on the same Wi-Fi are often isolated from your dev machine by client isolation, and typing a LAN IP into a phone is clunky anyway.
  • HTTPS-only browser APIs: Service Workers, the Web Crypto API, Geolocation, push notifications, and PWA installation all require a secure context. Self-signed certs across multiple devices are a hassle to manage.
  • Demoing work in progress: showing a client or teammate something running locally, without a full deploy.

A tunneling tool solves this by running a lightweight client that opens an outbound connection to a cloud relay, which then hands out a public URL and forwards traffic back down that connection to your local port. Because the connection is outbound-initiated, it gets through most NATs and firewalls without any router configuration.

Where ngrok Creates Friction for JS Developers

ngrok is a mature, capable product, but a few things about it specifically bother developers who live in the npm ecosystem:

It's a Go binary, not an npm package. The core agent is a closed-source, pre-compiled Go binary. Node.js wrappers exist, but they work by spawning that binary as a child process rather than behaving like a native JS module.

An account and authtoken are mandatory. This isn't outdated FUD — ngrok's own CLI documentation states plainly that the service requires you to sign up for an account to connect an agent, and attempting to run the agent without a verified account and authtoken now fails outright with an ERR_NGROK_4018 authentication error. There's no more anonymous, zero-signup quick start.

It's closed source. You can't audit the agent's code, and ngrok's pricing, plan names, and feature gating have changed multiple times over the product's history — something worth knowing if you're building a workflow that depends on specific free-tier limits staying put.

Enter Tunnelmole

Tunnelmole is an open-source tunneling tool built by developer Robbie Cahill, with both halves of the stack — the tunnelmole-client and the tunnelmole-service backend — written in TypeScript. The pitch is straightforward: no Go binary, no mandatory signup for the free tier, and a codebase JS developers can actually read.

Licensing (this is a two-license project, not one)

This is a detail worth getting right, since it affects what you can legally do with each half:

  • tunnelmole-client is MIT licensed — permissive, easy to vendor into your own tooling.
  • tunnelmole-service (the backend relay) is AGPLv3 licensed — if you modify it and make it available over a network, the AGPL's network-use clause applies. Tunnelmole's maintainer also offers a separate commercial source license for businesses that want more flexibility than AGPL allows.

Installing it

If you have Node.js 16.10 or later, the npm route works:

npm install -g tunnelmole
tmole 3000

You can also skip the Node version requirement entirely and grab a precompiled binary with Node bundled in:

curl -O https://install.tunnelmole.com/xD345/install && sudo bash install

Windows users can download tmole.exe directly and add it to their PATH.

Either way, running tmole <port> gives you both an HTTP and HTTPS URL immediately, no account required for the default hosted service:

$ tmole 8080
http://evgtkh-ip-49-145-166-122.tunnelmole.net is forwarding to localhost:8080
https://evgtkh-ip-49-145-166-122.tunnelmole.net is forwarding to localhost:8080

Using it programmatically

Tunnelmole also ships as an npm dependency for use inside Node/TypeScript code, supporting both ESM and CommonJS:

npm install --save tunnelmole
import { tunnelmole } from 'tunnelmole';
import express from 'express';

const app = express();
const PORT = 3000;

app.get('/', (req, res) => {
  res.send('Hello from the public web, routed through Tunnelmole!');
});

app.listen(PORT, async () => {
  console.log(`Server is running locally on http://localhost:${PORT}`);
  const url = await tunnelmole({ port: PORT });
  console.log(`Public URL available at: ${url}`);
});

The function is async and won't block your event loop. Installing as a dependency also drops node_modules/.bin/tmole into your project, which is handy for wiring into an npm script like "start-public": "npm run start && tmole 3000".

Two Things the Marketing Copy Tends to Skip

These don't show up in most comparison posts, but they matter for anyone evaluating Tunnelmole for anything beyond casual local testing.

Your IP is not hidden on the hosted service. Tunnelmole's own FAQ is direct about this: the service used to obscure origin IPs, but that was exploited by phishing operators, so Tunnelmole now attaches an X-Forwarded-For header with your real IP to every response — and for randomly generated subdomains, the IP is embedded in the URL itself. If IP privacy matters for your use case, self-hosting is the way to remove that behavior (you'd need to strip the header yourself), not the default hosted service.

Telemetry is on by default. The client collects anonymized data — your Node.js version, OS, and crash reports with stack traces — unless you opt out by setting TUNNELMOLE_TELEMETRY=0 in your environment. For a one-off tmole 3000 test this is a non-issue; for anything approaching a compliance-sensitive workflow, it's worth disabling explicitly and documenting that you did.

Self-Hosting Tunnelmole

This is the feature ngrok simply doesn't offer at any price. Since both the client and service are open source, you can run your own instance instead of relying on tunnelmole.com:

git clone git@github.com:robbie-cahill/tunnelmole-service.git
cd tunnelmole-service
npm install
cp config-instance.example.toml config-instance.toml
npm start

Point your tunnelmole-client config at your own server's WebSocket endpoint instead of the default SaaS instance, and you have a fully private tunneling setup with no third party in the loop, no telemetry you didn't add yourself, and no subscription needed for custom subdomains (which cost extra on the hosted service).

Two caveats worth flagging before you rely on this for anything real:

  • tunnelmole-service has no native HTTPS support. The maintainer's documentation is explicit about this — you need to put it behind Nginx (or similar) with a Let's Encrypt certificate to get HTTPS. The hosted tunnelmole.com service adds this infrastructure on top of the open-source code; a bare self-hosted instance won't have it out of the box.
  • The official hosted service isn't 100% identical to the open-source repo. Per the maintainer, tunnelmole.com runs the same open-source code plus closed-source billing/subscription verification and the added HTTPS infrastructure — that's the only proprietary layer, but it means "self-hosted" and "hosted" aren't running byte-identical software.

Feature Comparison

Attribute ngrok Tunnelmole
Core agent Go, closed-source binary TypeScript, open source
Account required for free tier Yes — verified account + authtoken enforced No, for the default hosted service
License Proprietary MIT (client) / AGPLv3 (service)
Self-hostable No Yes
Programmatic Node.js use Wrapper around external binary Native ESM/CommonJS module
IP hidden from destination N/A (ngrok's own infra) No — X-Forwarded-For + IP in URL on hosted service
Telemetry Not the focus of this piece On by default, opt-out via env var
Custom subdomains, hosted free tier Included (ngrok-branded domain) Requires paid subscription unless self-hosted

Where Each Tool Actually Costs Money

Since pricing is exactly the kind of thing that goes stale fastest in posts like this, here's ngrok's current published structure (verified directly against ngrok's pricing page, not a third-party aggregator):

Plan Price Includes
Free $0 $5 one-time usage credit (lasts one year, free plan only), up to 3 online endpoints, 1GB data transfer, 20k HTTP/S requests/month, interstitial warning page on endpoints
Hobbyist $8/mo billed annually ($10 month-to-month) $10 monthly usage credit, 3 online endpoints, 5GB data transfer, 100k requests included, no interstitial page, ngrok-branded domains
Pay-as-you-go $20/mo + usage Unlimited online endpoints and data transfer, bring-your-own domain, usage billed beyond included credit
Enterprise Custom SSO/SAML, SCIM, HIPAA BAAs, SOC 2 reports, dedicated support SLAs

Tunnelmole's hosted service is free for the core use case (random subdomain, HTTPS included); a subscription is only needed for a custom/reserved subdomain, and that requirement disappears entirely if you self-host.

Real-World Use Cases

Webhook development. tmole 3000 gives you a stable public HTTPS URL to hand to Stripe, Twilio, or GitHub's webhook settings, so you can set breakpoints and debug live events instead of writing stub payloads.

Mobile and cross-device testing. Because the tunnel is an outbound WebSocket connection, it gets around client-isolated Wi-Fi networks that would otherwise block a phone from reaching your dev machine directly.

HTTPS-gated browser features. Service Workers, PWA installation, and the Web Crypto API require a secure context. Tunnelmole's hosted HTTPS URLs sidestep the need to generate and trust self-signed certs across every test device.

Conclusion

ngrok remains a capable, enterprise-ready platform — but its account requirement and closed-source agent are real, current constraints, not outdated criticisms. Tunnelmole's pitch to JavaScript developers is legitimate: native npm installation, a readable TypeScript codebase, and a genuinely free, no-signup path for the common case. The trade-offs are just as real, though — telemetry is on by default, your IP is visible on the hosted service, and self-hosting for privacy means you're also on the hook for your own HTTPS termination. None of that makes Tunnelmole a bad choice; it just means "open source and self-hostable" isn't the same claim as "private by default," and it's worth knowing which one you're actually getting before you wire it into anything beyond a quick local demo.


Changelog

  • Removed: promotional/SEO framing ("Enter Tunnelmole, the tool that has recently gone viral," "the ultimate flex," "reclaiming your ecosystem" section headers) and AI-draft filler throughout; tightened language to match a technical, fact-first tone.
  • Corrected: original draft did not mention that ngrok now hard-enforces account signup and authtoken verification with a specific error (ERR_NGROK_4018) — added and sourced to ngrok's own CLI docs and a reproduced GitHub issue showing the failure. (Source: ngrok Agent CLI docs, runatlantis/atlantis#4218)
  • Added: exact current ngrok pricing table (Free/Hobbyist/Pay-as-you-go/Enterprise), pulled directly from ngrok's live pricing page rather than a general claim of "$0–$49/month." (Source: ngrok.com/pricing)
  • Added: confirmation and citation for the split license — MIT for tunnelmole-client, AGPLv3 for tunnelmole-service, plus the existence of a commercial licensing option. (Source: tunnelmole-service README)
  • Added: new "Two Things the Marketing Copy Tends to Skip" section covering (1) that the hosted Tunnelmole service does not hide your IP — it adds an X-Forwarded-For header and embeds IP in generated URLs — and (2) that telemetry (Node version, OS, crash reports) is collected by default with an opt-out env var. Neither fact appeared in the original draft. (Source: tunnelmole-client README/FAQ)
  • Added: clarification that tunnelmole-service has no native HTTPS support and requires a separate Nginx + Let's Encrypt setup for self-hosted HTTPS, plus the fact that the official hosted service runs the open-source code plus closed-source billing code and added HTTPS infrastructure — so self-hosted and hosted are not byte-identical. (Source: tunnelmole-service README)
  • Corrected: original draft implied npm install -g tunnelmole needs no Node version consideration; the actual requirement per the client README is Node.js 16.10+ specifically for the npm installation path (the precompiled binary/install script route has no such requirement since Node is bundled in). (Source: tunnelmole-client README)
  • Added: install-script and Windows binary installation methods as alternatives to npm, which the original draft omitted entirely. (Source: tunnelmole-client README)
  • Retained, verified accurate: self-hosting steps (git clone, cp config-instance.example.toml config-instance.toml, npm start) match the current tunnelmole-service README exactly. (Source: tunnelmole-service README)
  • Retained, verified accurate: programmatic ESM/CommonJS usage example matches the current tunnelmole-client README's documented API. (Source: tunnelmole-client README)

Comments