A small Node.js/Express app that shows your public IP address in a clean web UI and via simple API endpoints. Optionally, it enriches the result with IPInfo data (location, ISP, and hostname).
- Demo: https://ip.paulg.it
- License: MIT
- Web UI: IP (and hostname when available), location, ISP, dark mode, copy-to-clipboard
- API: HTML / JSON / Text formats + dedicated endpoints
- Optional IPInfo enrichment: works without a token, but fewer details
- Node.js: use the latest stable Node (or at least Node 18+)
- npm
git clone https://github.com/paulgit/whatsmyip.git
cd whatsmyip
npm install
npm run devThen open:
Copy the template and add your IPInfo token:
cp .env.example .envEdit .env and set:
IPINFO_TOKEN=your_token_hereGet a token:
docker build -t whatsmyip .
docker run --rm -p 3000:3000 -e IPINFO_TOKEN=your_token_here whatsmyipOpen:
If you want a smaller image and you’re building on Apple Silicon, build a single platform image:
docker build --platform linux/amd64 -t whatsmyip .This repo uses Option A:
docker-compose.ymlis production-like (no bind mounts,NODE_ENV=production)- Development overrides should live in
docker-compose.dev.yml(bind mounts,NODE_ENV=development, etc.)
From the project root:
docker compose up -dIf you need IPInfo enrichment, provide the env var:
IPINFO_TOKEN=your_token_here docker compose up -dCreate a docker-compose.dev.yml (not included here) and run:
docker compose -f docker-compose.yml -f docker-compose.dev.yml upNotes:
- Avoid bind mounts in production; they override the built image and can cause drift.
- In real production, prefer deploying a versioned image tag built in CI rather than building on the server.
Base URL below assumes local dev: http://localhost:3000
GET /GET /?format=html
GET /?format=json
Example:
{
"ip": "203.0.113.42",
"hostname": "example.com",
"city": "San Francisco",
"region": "California",
"country": "US",
"org": "AS15169 Google LLC"
}GET /?format=text
Example:
203.0.113.42
GET /api/ip→{ "ip": "…" }GET /api/info→{ "ip": "…", "hostname": "…", ... }(plus IPInfo fields when available)GET /health→{ "status": "ok", "timestamp": "…" }
You do not need to deploy anywhere to test this.
- Run
npm run dev - Visit
http://localhost:3000 - Confirm:
- IP appears
- hostname shows below the IP when present
- copy button copies the IP
- dark mode looks correct
Health:
curl -sS http://localhost:3000/healthIP only:
curl -sS http://localhost:3000/api/ipFull info:
curl -sS http://localhost:3000/api/infoWhen testing on localhost you’ll often see ::1 or private addresses. You can simulate a public client IP by providing a forwarded header:
curl -sS -H "x-forwarded-for: 8.8.8.8" http://localhost:3000/api/infoThis is helpful for confirming IPInfo hostname/location behavior without deploying behind a real proxy/CDN.
Create .env (optional):
PORT=3000
IPINFO_TOKEN=your_token_hereNotes:
- Without
IPINFO_TOKEN, the service still runs and returns your IP, but enrichment may be missing. - IPInfo has a free tier; see https://ipinfo.io/
whatsmyip/
├── server.js # Express server + API endpoints
├── public/ # Static frontend
│ ├── index.html
│ ├── style.css
│ └── app.js
├── package.json
├── Dockerfile
├── docker-compose.yml
└── .env.example
- Set
IPINFO_TOKENin.env(or in Docker-e IPINFO_TOKEN=...) - Confirm the token is valid
- Try simulating a public IP with
x-forwarded-foras shown above
If 3000 is already taken:
- set
PORT=3001in.envand restart - or stop the process using port 3000
- Geolocation data: https://ipinfo.io
- Original PHP script inspiration: https://github.com/TestoEXE/whatsmyip
MIT — see LICENSE.