FOR WEBHOOKS nodetonet.com
Use case Webhooks Dev tooling

Nodetonet for webhook development — tunnel localhost to a real HTTPS URL

Develop Stripe, GitHub and Slack webhooks locally without deploying — stable HTTPS URL, automatic Let's Encrypt cert, audit log, and a fair comparison with ngrok for webhook use cases.

N Nodetonet Team
May 15, 2026 8 min read

Webhook development is one of the most painful corners of modern back-end programming. Stripe sends a checkout.session.completed. GitHub fires a pull_request. Slack pings your slash command. None of them can reach localhost:3000 on your laptop, so the standard flow is deploy to staging, trigger the event, tail the logs, find the bug, push again — a 3-5 minute loop per iteration that shreds focus.

TL;DR: install the Nodetonet PC agent, create an HTTPS tunnel to port 3000, paste the stable public URL into Stripe or GitHub once, and from that moment on every webhook hits your local breakpoint within milliseconds — no redeploy, no staging lag.

Why the deploy loop costs you more than time

Every round-trip to staging is a context switch. By the time the logs show up you have already started reading something else. Worse, you cannot set breakpoints in staging; you would have to attach a remote debugger or litter the code with console.log calls. And reproducing intermittent webhook bugs — idempotency failures, out-of-order retries, race conditions between your handler and the provider's retry schedule — is nearly impossible because you cannot replay a specific signed delivery against your local code at will.

A tunnel collapses the entire loop into "save file, fire test event, hit your breakpoint." That is the development experience webhook providers expect you to have, and it is what this page is about.

How Nodetonet fits the webhook development workflow

Nodetonet's HTTP tunnel feature exposes any local port on your dev machine as a persistent public HTTPS URL. You can pick a stable subdomain like stripe-dev.yourname.nodetonet.com, or bring your own domain. The URL does not change when your laptop sleeps, does not change when you restart the tunnel agent, and does not change between coding sessions. Configure Stripe, GitHub and Slack once and never touch the webhook config again.

Step-by-step setup

  1. Sign up at /auth/register and top up a small amount of prepaid credit.
  2. Download and install the PC agent from /download. It runs in the system tray on Windows, macOS or Linux and idles at under 30 MB of RAM.
  3. In the panel under HTTP Tunnels, create a new tunnel. Source machine: your dev PC. Local port: 3000 (or whichever port your dev server uses). Public hostname: choose a free subdomain or your own domain.
  4. Copy the generated HTTPS URL. Paste it into the Stripe Dashboard under Developers → Webhooks, or into GitHub → Settings → Webhooks, or Slack's slash-command request URL.
  5. Fire a test event from the provider's UI. Within 200 ms your IDE hits the breakpoint. Iterate freely.

Code example — verifying a Stripe webhook signature

The handler below runs on localhost:3000. Expose it through the tunnel and paste the URL into Stripe. The critical detail is using express.raw on this one route so Stripe's HMAC signature check works against the original bytes:

// server.js
const express = require('express');
const stripe = require('stripe')(process.env.STRIPE_SECRET);
const app = express();
const SECRET = process.env.STRIPE_WEBHOOK_SECRET;

app.post('/webhook',
  express.raw({ type: 'application/json' }),
  (req, res) => {
    let event;
    try {
      event = stripe.webhooks.constructEvent(
        req.body, req.headers['stripe-signature'], SECRET
      );
    } catch (err) {
      return res.status(400).send('Bad signature');
    }
    console.log('Event received:', event.type, event.data.object.id);
    // Set a breakpoint here and iterate without redeploying
    res.json({ received: true });
  }
);

app.listen(3000, () => console.log('Listening on :3000'));

In the Stripe Dashboard, set the endpoint to https://stripe-dev.yourname.nodetonet.com/webhook. Click "Send test webhook." Your process logs the event in under 200 ms. Change the handler, save, and the hot-reload means the next test event hits your updated code instantly — without any redeploy.

Nodetonet vs ngrok for webhook development

Both tools tunnel local ports to public HTTPS URLs. The table below covers the differences that matter for a typical webhook development workflow. We have described ngrok's publicly documented features accurately and honestly — this is not a one-sided comparison.

Feature Nodetonet ngrok Free ngrok Personal ($8/mo)
Stable public URL Yes — subdomain or custom domain Random URL, changes every session Yes — reserved domain
Automatic HTTPS / TLS cert Yes, Let's Encrypt, wildcard Yes Yes
Custom domain (own CNAME) Yes, no extra fee No Yes
Request audit log 30-day log, panel + REST API Limited session-only inspector Extended inspector
One-click Replay Not yet (roadmap) Yes (web inspector) Yes (web inspector)
IP allow-listing Yes — built-in, per-tunnel No Yes (IP policy)
Idle cost Zero — prepaid credit, no subscription Free tier (limited) $8/month regardless of use
Multiple local ports at once Yes — one tunnel per port, billed per use 1 tunnel on free Yes

The honest summary: ngrok's one-click Replay is the feature Nodetonet does not have yet. If replaying specific signed webhook deliveries from a GUI is a daily part of your debugging workflow, ngrok Personal is currently the stronger choice for that specific task. For stable URLs, custom domains, IP restriction and cost efficiency, Nodetonet competes well — especially if you already use Nodetonet for mobile proxies or rotating proxies and want one platform for everything. See our full Nodetonet vs ngrok comparison for more.

Using the audit log as a manual Replay

While the one-click UI is on the roadmap, the 30-day audit log in the panel already gives you the raw material to reproduce any delivery. Every logged request includes the full headers and payload. From there you can re-fire it against your local server with a single curl command:

# Fetch the raw body of a specific tunnel request
curl -s -H "Authorization: Bearer $NTN_KEY"   "https://nodetonet.com/api/v1/proxies/prx_abc123/requests/req_xyz789"   | jq -r '.data.body'   | curl -X POST http://localhost:3000/webhook        -H "Content-Type: application/json"        -H "Stripe-Signature: $(cat .stripe-sig)"        -d @-

It takes a few more keystrokes than a button click, but it works and it means you never lose access to a specific problematic delivery. Check the REST API first call guide and the audit log guide for the full syntax.

Locking down the tunnel to your webhook provider

Leaving a public HTTPS URL wide open is fine during initial development, but before long-running setup you should restrict access to known source IPs. Stripe publishes its webhook delivery IP ranges; GitHub provides them via https://api.github.com/meta. Paste those CIDR blocks into the tunnel's IP allow-list in the panel. Any request from an unknown IP gets a 403 before it ever reaches your dev machine. This mirrors the approach described in our IP allow and deny lists post.

Testing GitHub and Slack webhooks

The same tunnel serves every webhook provider. A GitHub repository webhook pointed at https://ci.yourname.nodetonet.com/github fires events to your local CI runner the instant code is pushed. A Slack slash command URL pointed at https://slack.yourname.nodetonet.com/commands/myapp lets you iterate on the response payload in real time, in your local environment, with full access to your local database and file system — none of which is available in a typical staging environment.

For monitoring tunnel health once set up, see monitoring your tunnel health. For programmatic tunnel management from scripts, programmatic tunnel creation in Python shows a reusable client.

When this is not the right fit

Get started

Ready to stop deploying just to test a webhook? Create a free account, install the PC agent from /download, and have your first tunnel running in under five minutes. Browse HTTP tunnels for the full feature set, or check our proxy checker to verify any tunnel is live before pointing a payment provider at it.

Frequently asked questions

Will the public URL stay the same if I close my laptop?
Yes. The subdomain — or any custom domain you attach — is reserved to your account, not to the live tunnel connection. Close your laptop, restart it, relaunch the agent, and the URL is unchanged. Stripe and GitHub webhook configurations stay valid indefinitely.
Does Nodetonet have anything like ngrok's "Replay" feature?
Not as a one-click UI button yet — that is on the public roadmap. Today you can retrieve any of the last 30 days of logged requests via the REST API and re-fire them against your local server with curl. It takes a few extra keystrokes but achieves the same result without losing the original signed payload.
Can I lock the tunnel so only Stripe or GitHub can reach it?
Yes. Open the tunnel's detail page in the panel and set an IP allow-list. Stripe publishes its webhook source IP ranges at stripe.com/docs/ips; GitHub publishes them via api.github.com/meta. Paste the CIDR ranges in and every request from any other source gets a 403 before it reaches your machine.
Can I use the same tunnel for multiple webhook providers at once?
Yes, as long as your local server handles the different routes. You can point Stripe at /webhook/stripe, GitHub at /webhook/github, and Slack at /webhook/slack all on the same tunnel URL. Each provider's events arrive at the correct route and your local handler processes them normally.
How much does keeping a dev tunnel open cost?
Nodetonet bills on prepaid credit with no monthly subscription. An always-on dev tunnel costs roughly $1 per month. If you stop the tunnel at weekends or on vacation, you pay for only the hours it was running. There is no minimum charge and idle tunnels cost nothing.
Do I need a Nodetonet mobile proxy to use HTTP tunnels?
No. HTTP tunnels are a separate product. You install a lightweight Windows, macOS or Linux PC agent on your dev machine — no phone or SIM required. Mobile proxies and HTTP tunnels are independent features within the same platform, billed from the same prepaid credit balance.
Can I share one tunnel URL with a teammate working on the same webhook handler?
You can share the URL publicly, but the tunnel routes to one source machine. If both of you need to receive webhook deliveries locally, create two separate tunnels pointing to each dev machine. Configure the provider with both URLs (if it supports multiple endpoints) or use a shared staging environment for coordinated testing.

Stop deploying to test a webhook

One stable HTTPS URL. Automatic cert. Prepaid credit, no subscription. Sign up and ship faster today.