🚀 Free & open source ngrok alternative - Tunnel localhost to the internet via Cloudflare Edge
NPort is a powerful, lightweight ngrok alternative that creates secure HTTP/HTTPS tunnels from your localhost to public URLs using Cloudflare's global edge network. No configuration, no accounts, just instant tunnels with custom subdomains!
Perfect for:
- 🚀 Development environments - Share your local work instantly
- 🔒 Testing webhooks - Receive webhooks from GitHub, Stripe, PayPal, etc.
- 📱 Mobile testing - Test your web app on real devices
- 🛠️ API development - Debug integrations with external services
- 👥 Demo to clients - Show your progress without deployment
- ⚡ Instant Setup: One command to expose your localhost
- 🌐 Custom Subdomains: Choose your own URL (e.g.,
myapp.nport.link) - 🔒 Automatic HTTPS: SSL/TLS encryption via Cloudflare
- 🌍 Global Edge Network: Fast connections worldwide via Cloudflare
- 📡 WebSocket Support: Full WebSocket and Server-Sent Events support
- 🎯 No Configuration: Works out of the box
- 💻 Cross-Platform: Windows, macOS, and Linux support
- 🗣️ Multilingual: English and Vietnamese UI support
- 🆓 100% Free: No accounts, no limits, no paywalls
- 🔓 Open Source: MIT licensed
- Node.js >= 20.0.0
- npm >= 10.0.0
Check your versions:
node --version
npm --version# Global installation
npm install -g nport
# Or use npx without installation
npx nport 3000 -s myappnpm install -g git+https://github.com/tuanngocptn/nport.gitExpose port 3000 with a random subdomain:
nport 3000Output:
╭────────────────────────────────────────────────────────╮
│ N P O R T ⚡️ Free & Open Source from Vietnam │
╰────────────────────────────────────────────────────────╯
⠋ Creating tunnel for port 3000...
🚀 WE LIVE BABY!
👉 https://user-1234.nport.link 👈
───────────────────────────────────────────────────────
⏱️ Time: 4h remaining
✔ [1/2] Connection established...
✔ [2/2] Compression enabled...
───────────────────────────────────────────────────────
🔥 KEEP THE VIBE ALIVE?
(Made with ❤️ in Vietnam)
⭐️ Drop a Star: https://github.com/tuanngocptn/nport
☕️ Buy Coffee: https://buymeacoffee.com/tuanngocptn
Choose your own subdomain:
nport 3000 -s myapp
# Creates: https://myapp.nport.linkOr using long form:
nport 3000 --subdomain myapp# Next.js
npm run dev
nport 3000 -s my-nextjs-app
# React (Create React App)
npm start
nport 3000 -s my-react-app
# Vue.js
npm run dev
nport 8080 -s my-vue-app
# Express.js
node server.js
nport 3000 -s my-api# Start your local webhook receiver
node webhook-receiver.js
# Expose it to the internet
nport 4000 -s my-webhooks
# Use in GitHub webhook settings:
# https://my-webhooks.nport.link/webhook# Start your local dev server
npm run dev
# Create tunnel
nport 3000 -s mobile-test
# Open on your phone:
# https://mobile-test.nport.linknport <port> [options]| Option | Short | Description | Example |
|---|---|---|---|
<port> |
- | Local port to tunnel (default: 8080) | nport 3000 |
--subdomain |
-s |
Custom subdomain | nport 3000 -s myapp |
--backend |
-b |
Custom backend URL (temporary) | nport 3000 -b https://your-backend.com |
--set-backend |
- | Save backend URL permanently | nport --set-backend https://your-backend.com |
--language |
-l |
Set language (en/vi) or prompt | nport 3000 -l vi |
--version |
-v |
Show version information | nport -v |
NPort supports multiple languages with automatic detection on first run.
# Set language directly
nport 3000 --language en # English
nport 3000 -l vi # Vietnamese
# Open language selection menu
nport --language # Interactive prompt
nport -l # Interactive promptOn first run or when using --language without a value, you'll see an interactive language picker. Your choice is automatically saved for future sessions.
NPort uses a default backend at https://api.nport.link, but you can use your own backend server.
Use a custom backend for just the current session:
# Use custom backend via CLI flag
nport 3000 --backend https://your-backend.com
nport 3000 -b https://your-backend.com
# Use custom backend via environment variable
export NPORT_BACKEND_URL=https://your-backend.com
nport 3000
# Combine with other options
nport 3000 -s myapp -b https://your-backend.comSave a backend URL to use automatically in all future sessions:
# Save backend URL permanently
nport --set-backend https://your-backend.com
# Now all future commands will use this backend
nport 3000 # Uses saved backend
nport 3000 -s myapp # Uses saved backend
# Clear saved backend (return to default)
nport --set-backend
# Override saved backend temporarily
nport 3000 -b https://different-backend.comConfiguration Priority:
- CLI flag (
--backendor-b) - Highest priority - Saved config (
--set-backend) - Environment variable (
NPORT_BACKEND_URL) - Default (
https://api.nport.link) - Lowest priority
Configuration Storage:
Your backend preference is saved in ~/.nport/config.json
This is useful if you want to:
- Self-host: Run your own NPort backend (see server/ directory)
- Development: Test against a local backend
- Custom domains: Use your own domain for tunnel URLs
- Enterprise: Use a company-hosted backend server
# Check current version and updates
nport -v
nport --version- You run
nport 3000 -s myapp - NPort creates a Cloudflare Tunnel
- DNS record is created:
myapp.nport.link→ Cloudflare Edge - Cloudflared binary connects your localhost:3000 to Cloudflare
- Traffic flows through Cloudflare's global network to your machine
- On exit (Ctrl+C), tunnel and DNS are automatically cleaned up
Internet → Cloudflare Edge → Cloudflare Tunnel → Your localhost:3000
(https://myapp.nport.link)
nport/
├── src/ # TypeScript source files
│ ├── index.ts # Entry point
│ ├── tunnel.ts # Tunnel orchestration
│ ├── api.ts # Backend API client
│ ├── args.ts # CLI argument parser
│ ├── binary.ts # Cloudflared process manager
│ ├── ui.ts # Console UI components
│ ├── lang.ts # Multilingual support
│ ├── types/ # TypeScript type definitions
│ └── ...
│
├── tests/ # Unit tests (vitest)
├── dist/ # Compiled output
├── bin/ # cloudflared binary (downloaded)
│
├── server/ # Backend (Cloudflare Worker)
├── website/ # Static landing page
├── docs/ # Documentation
│ ├── ARCHITECTURE.md # Technical architecture
│ ├── API.md # API reference
│ └── CONTRIBUTING.md # Contribution guide
└── .ai/ # AI context files
- HTTPS by default: All tunnels use SSL/TLS encryption
- Cloudflare protection: DDoS protection and security features
- Automatic cleanup: Tunnels are removed when you stop the process
- No data logging: We don't store or log your traffic
- Privacy: Anonymous analytics (can be disabled with
NPORT_ANALYTICS=false)
| Feature | NPort | ngrok |
|---|---|---|
| Price | 100% Free | Free tier limited |
| Custom subdomains | ✅ Always | ❌ Paid only |
| HTTPS | ✅ Always | ✅ |
| Account required | ❌ No | ✅ Yes |
| Time limits | ❌ None (4h auto-cleanup) | |
| Open source | ✅ MIT | ❌ Proprietary |
| Global network | ✅ Cloudflare | ✅ ngrok Edge |
| Multilingual | ✅ EN/VI | ❌ English only |
NPort automatically cleans up resources when you:
- Press Ctrl+C to exit
- Kill the process
- Terminal closes
The cleanup process:
- ✅ Deletes DNS record (
myapp.nport.link) - ✅ Removes Cloudflare Tunnel
- ✅ Stops cloudflared process
Tunnels also auto-cleanup after 4 hours to prevent resource waste.
If you see "Cloudflared binary not found":
npm install -g nport --forceMake sure your local server is running on the specified port:
# Check if something is listening on port 3000
lsof -i :3000 # macOS/Linux
netstat -ano | findstr :3000 # WindowsChoose a different subdomain name:
nport 3000 -s myapp-v2The ERR Cannot determine default origin certificate path warning is harmless and can be ignored. It appears because cloudflared checks for certificate-based authentication (we use token-based instead).
To change your language preference:
nport --language
# or
nport -lThen select your preferred language from the menu.
- 🇺🇸 English (
en) - Default - 🇻🇳 Vietnamese (
vi) - Tiếng Việt
Want to add your language? Contributions are welcome! Check out the Contributing Guide.
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
See docs/CONTRIBUTING.md for detailed guidelines.
# Clone the repository
git clone https://github.com/tuanngocptn/nport.git
cd nport
# Install dependencies
npm install
# Build TypeScript
npm run build
# Run tests
npm test
# Run CLI locally
node dist/index.js 3000 -s testIf you find NPort useful, please consider supporting the project:
- ⭐ Star on GitHub
- ☕ Buy me a coffee
- 💬 Share with your friends and colleagues
- 🐛 Report bugs
- 🌍 Add translations
MIT License - Feel free to use NPort in your projects!
-
Created by Nick Pham from Vietnam
-
Inspired by ngrok and localtunnel
-
Powered by Cloudflare Tunnels
- 🌐 Website: https://nport.link
- 📦 NPM: https://www.npmjs.com/package/nport
- 💻 GitHub: https://github.com/tuanngocptn/nport
- 📧 Email: tuanngocptn@gmail.com
Made with ❤️ in Vietnam by Nick Pham
