Why adb reverse is needed for accessing a local server from Android

·3 min read·mobile

If you’ve ever tried to hit your local Rails server from a physical Android device, you’ve probably run into this: your phone can’t reach localhost:3000. The fix is a simple command, but understanding why it works is worth explaining.

The problem: localhost means different things

When you run rails server on your machine, it binds to localhost:3000. Your browser can reach it because “localhost” on your computer means… your computer.

But when your Android phone tries to hit localhost:3000, it’s looking for a server running on the phone itself. There’s nothing there. The phone’s localhost is the phone, not your development machine.

What adb reverse does

The fix is this:

adb reverse tcp:3000 tcp:3000

This command creates a reverse port forwarding tunnel over USB. It tells the Android device: “When something on you tries to connect to port 3000, forward that traffic through the USB connection to port 3000 on the computer.”

After running this, your Android app can hit http://localhost:3000 and it will actually reach your development server.

Why is it called “reverse”?

ADB has two forwarding directions:

  • adb forward - traffic from computer goes to device
  • adb reverse - traffic from device goes to computer

Since we want the phone to reach our computer’s server, we need “reverse” forwarding. The phone initiates the connection, and it gets tunneled back to the computer.

Alternative: WiFi approach

If you don’t want to use USB, you can expose your server on your local network:

rails server -b 0.0.0.0

Then find your computer’s local IP (something like 192.168.1.42) and hit that from your phone:

http://192.168.1.42:3000

This works, but has downsides: your IP might change, both devices need to be on the same network, and you’re exposing your dev server to the whole network. The USB approach is more reliable for development.

Emulator difference

If you’re using the Android emulator instead of a physical device, you don’t need adb reverse. The emulator has a special IP address 10.0.2.2 that maps to your host machine’s localhost. So your emulator can just hit:

http://10.0.2.2:3000

This is built into the emulator. Physical devices don’t have this mapping, which is why they need the reverse tunnel.

Summary

  • Physical Android device can’t reach your computer’s localhost
  • adb reverse tcp:3000 tcp:3000 creates a USB tunnel
  • After that, localhost:3000 on the phone reaches your computer
  • Emulators don’t need this because 10.0.2.2 already maps to host localhost