Guides7 min read·

How to open localhost on your phone (Wi-Fi, USB, tunnel)

Typing localhost on your phone opens the phone itself. How to reach your dev server over Wi-Fi, USB or a tunnel, and fix the HTTPS features that break on an IP.

You can't just type localhost:3000 on your phone: localhost always means "this device", so your phone looks for a web server on itself and finds nothing. To reach your computer, connect both to the same Wi-Fi, start your dev server so it listens on the network, and open your computer's local IP address on the phone, for example http://192.168.1.20:3000. If the network or HTTPS gets in the way, use a USB port forward or a tunnel.

Why localhost means the phone itself

localhost is a nickname for 127.0.0.1, the "loopback" address every device uses to talk to itself. When your laptop opens localhost:3000, it reaches the dev server on the laptop. When your phone opens it, it reaches the phone.

There's a second catch: many dev servers only listen on loopback, so even if the phone knocks on the right address, nobody answers. The fix has two parts: find your computer's address on the network, and make the server listen there.

Option 1: Same Wi-Fi, your computer's IP address

Step 1: Find your computer's local IP

On a Mac, run this in Terminal:

ipconfig getifaddr en0

en0 is usually Wi-Fi; if nothing prints, try en1. Or look in System Settings → Wi-Fi → Details next to your network.

On Windows, run ipconfig in Command Prompt or PowerShell and find IPv4 Address under "Wireless LAN adapter Wi-Fi".

Home network addresses usually start with 192.168. or 10..

Step 2: Make your dev server listen on the network

Vite (React, Vue, Svelte and many AI-generated projects) listens on localhost only. Pass --host:

npm run dev -- --host

The -- hands the flag to Vite instead of npm. Vite then prints a Network: address you can type on the phone. To make it permanent, set server: { host: true } in vite.config.js.

Next.js already listens on all network interfaces (0.0.0.0) by default and prints a Network address. To be explicit:

npx next dev -H 0.0.0.0

Current Next.js versions also block cross-origin requests to their development files by default. If the page appears on your phone but nothing is clickable and the terminal mentions a blocked cross-origin request, add your IP to allowedDevOrigins (Next.js docs):

// next.config.js
module.exports = {
  allowedDevOrigins: ['192.168.1.20'],
};

A folder of plain HTML files: Python's built-in server already listens on all interfaces:

python3 -m http.server 8000

Other tools usually have a similar --host option; check their docs.

Step 3: Open it on the phone

Type the full address, including http:// and the port: http://192.168.1.20:5173 for Vite, :3000 for Next.js, :8000 for Python. Leave off the port and the phone tries port 80, where nothing is listening.

Step 4: Let it through the firewall

  • Mac: if the firewall is on, macOS asks whether "node" (or "Python") may accept incoming network connections. Click Allow. If you clicked Deny earlier, change it under System Settings → Network → Firewall → Options.
  • Windows: a Windows Security alert asks which networks the app may use. Allow Private networks, and make sure your Wi-Fi is set to Private, not Public.

Still nothing? Guest and office Wi-Fi often stop devices seeing each other (called client isolation). Use a tunnel (option 3) instead.

One safety note: listening on the network means anyone on the same Wi-Fi can open your dev server. Fine at home; think twice in a café.

The HTTPS catch: what breaks on an IP address

Browsers treat http://localhost as a secure context even without HTTPS. http://192.168.1.20 isn't one. So features that require a secure context quietly stop working on your phone:

  • service workers (installable apps, offline mode)
  • camera and microphone (getUserMedia) and geolocation
  • the clipboard API (navigator.clipboard) and the share sheet (navigator.share)
  • crypto.randomUUID() and crypto.subtle
  • passkeys

Two more to watch. Cookies marked Secure aren't saved over plain HTTP on an IP address, so logins can fail silently. And sign-in providers (OAuth) only send people back to addresses you registered, usually http://localhost:3000.

If you hit these, use USB forwarding (option 2), which keeps a real localhost on the phone, or a tunnel (option 3), which gives you HTTPS.

Option 2: USB port forwarding (Android)

Turn on USB debugging (Settings → About phone → tap Build number seven times → Developer options → USB debugging), plug the phone in, and run:

adb reverse tcp:3000 tcp:3000

Now http://localhost:3000 on the phone reaches port 3000 on your computer, and because it's localhost, it counts as a secure context. adb comes with Android's platform tools. Prefer clicking? Desktop Chrome's chrome://inspect#devices page has a Port forwarding setting that does the same job.

There's no built-in equivalent for iPhone. Use Wi-Fi or a tunnel, or the iOS Simulator on a Mac, where localhost already means your Mac.

Option 3: A tunnel (any network, with HTTPS)

A tunnel gives your local server a temporary public HTTPS address. Two common ones:

# Cloudflare Quick Tunnel: no account needed
cloudflared tunnel --url http://localhost:3000

# ngrok: needs a free account and auth token first
ngrok http 3000

Cloudflare prints a random trycloudflare.com address; ngrok prints its own. Open it on the phone, over Wi-Fi or mobile data.

The caveats:

  • It's public. Anyone with the link can reach your dev server. Stop the tunnel when you're done and keep secrets out of the page.
  • Vite blocks unknown hostnames. You'll see a "Blocked request. This host (…) is not allowed" message. Add the tunnel's domain to your existing config (Vite docs):
// vite.config.js
export default {
  server: {
    allowedHosts: ['.trycloudflare.com'],
  },
};

A leading dot allows every subdomain. Avoid allowedHosts: true, which Vite warns lets any website send requests to your dev server.

  • Next.js wants the tunnel in allowedDevOrigins too, for example '*.trycloudflare.com'.
  • Hard-coded localhost URLs break. If your code calls http://localhost:3000/api, the phone calls itself. Use relative URLs like /api.
  • Sign-in callbacks need the tunnel address added in your auth provider's settings.
  • Quick Tunnels have limits. Cloudflare caps them at 200 in-flight requests and doesn't support Server-Sent Events, which many AI chat apps use to stream replies. If your chatbot hangs on the phone, that's why.

Option 4: Skip the phone for layout checks

If all you want to know is "does it fit on phone screens", you don't need the phone.

doesitfit. Open the app in Chrome, type localhost:3000 and press Try it on. Click Allow when Chrome asks about access to your local network. You'll see your dev site on real sizes at once, from a Galaxy S25 (360 × 780) to an iPhone 17 Pro (402 × 874) and up to laptops. Use the localhost address, not your IP: browsers won't show a plain-HTTP IP address inside an HTTPS site. Safari won't show localhost inside it either, so stick to Chrome for this.

Your AI. The local doesitfit MCP server runs on your computer, so Claude Code or Codex can open localhost at real screen sizes, see what spills and fix it:

claude mcp add doesitfit-local -- npx -y https://doesitfit.lol/downloads/doesitfit-mcp-1.0.0.tgz

It needs Node.js and Chrome (or Edge, Brave or Chromium). Setup for other apps is on /connect, and checking your website from Claude, ChatGPT or Codex walks through it.

Simulators. In the iOS Simulator on a Mac, localhost is your Mac, so it just works. In Android's emulator, your computer is 10.0.2.2. More in how to test your website on mobile without a phone.

Browser device mode works on localhost too, with the gaps listed in why DevTools device mode isn't accurate. What none of these tell you is how the site feels in the hand: the keyboard, tap targets, speed. For that, use options 1 to 3 before launch.

Does your site fit?

Paste your address (or localhost:3000). doesitfit shows it on real screen sizes at once and tells you, bluntly, where it spills.

Free, no sign-up. Or ask Claude, ChatGPT or Codex to check it.

When it doesn't work

What you see Likely cause Fix
Phone can't connect or times out Server listens on localhost only, or the firewall blocks it --host or -H 0.0.0.0; allow it in the firewall
Works at home, not at the office Wi-Fi blocks device-to-device traffic Tunnel or USB
"Blocked request. This host (…) is not allowed" Vite's allowed hosts Add the domain to server.allowedHosts
Page shows but buttons do nothing Blocked dev files or hard-coded localhost URLs allowedDevOrigins; relative URLs
Camera, clipboard or login broken Not a secure context on an IP address USB forwarding or a tunnel

If you'd rather let your AI sort it out, paste this into Claude Code, Cursor or ChatGPT from your project:

I want to open my dev server on my phone over Wi-Fi. Tell me the exact command to start it so it listens on my local network, how to find my computer's IP address on my Mac/Windows PC, and what in my project (allowed hosts, hard-coded localhost URLs, Secure cookies, login redirect URLs) will break when I open it at http://MY-IP:PORT. Fix those for development only.

The quick recipe

  1. Same Wi-Fi, npm run dev -- --host, open the Network address on the phone.
  2. Something security-related broken? Use adb reverse on Android, or a tunnel.
  3. Only checking layout? Skip the phone: open localhost in doesitfit, or let your AI check it.
  4. Before launch, go through the vibe coding launch checklist on a real phone.

Questions people ask

Why doesn't localhost work on my phone?

Because localhost always means the device you're typing on. Your phone looks for a web server on itself, finds none, and gives up. Use your computer's local IP address instead, for example http://192.168.1.20:3000.

How do I find my computer's IP address?

On a Mac, run ipconfig getifaddr en0 in Terminal (try en1 if nothing prints) or look in System Settings → Wi-Fi → Details. On Windows, run ipconfig and read the IPv4 Address under your Wi-Fi adapter.

Why does my site work on my laptop but not on my phone over Wi-Fi?

Usually the dev server only listens on localhost, a firewall blocks it, or the Wi-Fi stops devices seeing each other. Start the server with --host (Vite) or -H 0.0.0.0 (Next.js), allow it in the firewall, or use a tunnel.

Is it safe to use ngrok or Cloudflare Tunnel for my dev server?

It's fine for a quick test, but the address is public: anyone with the link can open your dev server. Stop the tunnel when you're done and don't put secrets in the page.

Keep reading