# Spoofing an iPhone's GPS location with a Raspberry Pi

> Using Apple's developer tools to trick Location Services

By Zsolt Bizderi · Published 2026-10-12
Canonical: https://ambientnode.uk/spoofing-an-iphone-s-gps-location-with-a-raspberry-pi

Changing your apparent location with a VPN is common knowledge now, even outside tech circles. But a VPN only changes your IP address. I wanted to know whether the GPS coordinates an iPhone reports to Location Services could be spoofed.

The first results were third-party apps like iMyFone, which looked dodgy at best. Digging further, I found a whole community built around this, mostly Pokémon Go players faking their location to play the game. There are even companies selling dedicated hardware that spoofs GPS coordinates. If hardware can do it, there had to be a software route.

And there is: Apple's own developer tooling lets you simulate a GPS location on a connected device. This is traditionally used by developers to test geofencing capabilities and see how their apps behave in different places around the world. So I set out to build a small box that does it automatically. Plug the iPhone in and it jumps to a preset location. Unplug it and it's back to reality.

> iOS Developer Mode lowers some of iOS's protections, so I wouldn't leave it enabled on a daily-driver phone longer than needed. And if you're tempted to use this for things like Pokémon Go, Niantic actively bans location spoofers, so treat that as your risk to take.

***

## How does it work?

When you debug an app in Xcode, you can tell the phone to pretend it's somewhere else. That feature runs over Apple's developer services (DVT), which are available once the phone has Developer Mode enabled and a Developer Disk Image mounted.

[pymobiledevice3](https://github.com/doronz88/pymobiledevice3) is an open-source Python implementation of those same protocols. It runs on Linux, which means a Raspberry Pi can do what Xcode does, without a Mac.

From iOS 17 onwards, developer services run over an encrypted tunnel, so a background daemon (`tunneld`) needs to be running to broker that connection.

***

## What you need

* Raspberry Pi + microSD with a decent 5 V / 2.5 A+ power supply. The phone draws charging current through the Pi, and undervoltage kills USB.
* A proper USB data cable. Charge-only cables won't enumerate.
* An iPhone that supports Developer Mode (iOS 16+). iOS 17.4+ preferably.
* Wi-Fi for the Pi, so you can SSH in later and so it can reach Apple's servers when mounting the disk image.

## 1\. Flash the SD card

Use Raspberry Pi Imager to write Raspberry Pi OS Lite. In the Imager settings:

* Hostname: `pispoof`
* User: `youruser`
* Enable SSH
* Add your Wi-Fi details

Boot the Pi and SSH in:

```
ssh youruser@pispoof.local
```

## 2\. Install dependencies

```
sudo apt update && sudo apt full-upgrade -y
sudo apt install -y usbmuxd python3-venv python3-pip
python3 -m venv ~/pmd
~/pmd/bin/pip install --upgrade pip
~/pmd/bin/pip install pymobiledevice3
```

## 3\. Pair the phone \(one\-time\)

Plug the phone in and unlock it, then run:

```
~/pmd/bin/pymobiledevice3 usbmux list
```

Tap **Trust** on the phone and run the command again. You should see the device's JSON.

Next, check Developer Mode:

```
~/pmd/bin/pymobiledevice3 amfi developer-mode-status
```

If it's `false`, enable it:

```
~/pmd/bin/pymobiledevice3 amfi enable-developer-mode
```

The phone reboots. Unlock it and confirm the Developer Mode prompt. If the command refuses (it may not work while a passcode is set), run `amfi reveal-developer-mode` instead, then turn it on manually on the iPhone under Settings > Privacy & Security > Developer Mode.

Finally, mount the Developer Disk Image:

```
~/pmd/bin/pymobiledevice3 mounter auto-mount
```

This needs internet access and the image unmounts every time the phone reboots. The script below re-mounts it automatically.

## 4\. Test it manually

In one terminal, start the tunnel daemon as root:

```
sudo ~/pmd/bin/pymobiledevice3 remote tunneld
```

Leave that running, and in a second terminal set a location:

```
~/pmd/bin/pymobiledevice3 developer dvt simulate-location set --tunnel '' -- 51.5074 -0.1278
```

Note the `dvt` and `--tunnel ''`. The older non-`dvt` command is the pre-iOS 17 service and no longer works.

Open Maps on the phone and you should be standing in the middle of Trafalgar Square.
![image.png](/media/d25f1549-e675-414a-8e66-e14d175ea1a2/489.webp)

To undo it:

```
~/pmd/bin/pymobiledevice3 developer dvt simulate-location clear --tunnel ''
```

If you get `Failed to start service`, run `mounter auto-mount` first. If iOS 17+ complains about needing a tunnel, make sure `tunneld` is running as root in the other terminal.

***

## 5\. Automating the process for plug\-and\-play location spoofing

You will need two systemd services: one keeps `tunneld` running, the other watches for a phone and applies the location.

**`/etc/systemd/system/tunneld.service`**

```
[Unit]
Description=pymobiledevice3 tunneld
After=usbmuxd.service

[Service]
ExecStart=/home/youruser/pmd/bin/pymobiledevice3 remote tunneld
Restart=always
RestartSec=3

[Install]
WantedBy=multi-user.target
```

**`/usr/local/bin/spoof-location.sh`** (set `LAT` and `LON` to your preset)

```
#!/bin/bash
LAT=51.5074
LON=-0.1278
P=/home/youruser/pmd/bin/pymobiledevice3

while true; do
  if $P usbmux list 2>/dev/null | grep -q UniqueDeviceID; then
    $P mounter auto-mount >/dev/null 2>&1   # no-op if already mounted
    if $P developer dvt simulate-location set --tunnel '' -- "$LAT" "$LON" >/dev/null 2>&1; then
      sleep 60   # re-apply every minute, harmless
    else
      sleep 5    # tunnel not ready or phone locked, retry
    fi
  else
    sleep 3      # no phone connected
  fi
done
```

**`/etc/systemd/system/spoof-location.service`**

```
[Unit]
Description=Auto iPhone location spoof
After=tunneld.service
Requires=tunneld.service

[Service]
ExecStart=/usr/local/bin/spoof-location.sh
Restart=always
RestartSec=3

[Install]
WantedBy=multi-user.target
```

Enable everything:

```
sudo chmod +x /usr/local/bin/spoof-location.sh
sudo systemctl daemon-reload
sudo systemctl enable --now tunneld spoof-location
sudo systemctl status tunneld spoof-location
```

Reboot the Pi, plug the phone in, wait about 20 seconds and check Maps.

Once it works, pin the working version of pymobiledevice3:

```
~/pmd/bin/pip freeze | grep pymobiledevice3 > ~/pinned.txt
```

If an update ever breaks things, roll back with `~/pmd/bin/pip install -r ~/pinned.txt`.

***

## Notes on behaviour

* **Plugged in:** spoofed within 10 to 20 seconds.
* **Unplugged:** back to the real location.
* **Reboots:** the Pi will spin up the services on a reboot, but after the phone reboots, the iPhone has to be unlocked once before the Developer Disk Image can re-mount.
* **iOS major updates:** I did not test this, but I suppose it could break things. SSH in, run `~/pmd/bin/pip install -U pymobiledevice3` and retest.
* **New phone:** SSH in, plug it in and repeat step 3 (Trust and Developer Mode).
