ios-location-spoofer: Faking iPhone GPS Through an HTTPS Proxy Module
Standalone iOS app to spoof GPS location without jailbreak. Includes Shadowrocket/Surge/Loon/QX/Stash module.
At a glance
- What is it?
- A proxy-based approach to changing an iPhone's network location without jailbreak, a computer or a developer account. The module rewrites Apple's WLOC responses, and the hard part is not the rewrite but the iOS 26 cache.
- Who is it for?
- Adopt it if you already run one of the five supported proxies, can install and trust a CA certificate, and accept that iOS 26 and 27 require a full device restart before a new coordinate shows up. Do not adopt it if you need GPS-level spoofing, if you cannot tolerate a man-in-the-middle certificate on the device, or if you expect a one-tap app.
- Can I use it commercially?
- Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
- Is it still maintained?
- Yes. The repository last received commits 15 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 17, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
What ios-location-spoofer actually changes, and what it leaves alone
An iPhone does not only use GPS. It also asks Apple where it is by sending a list of nearby Wi-Fi BSSIDs and cell tower identifiers to Apple's location service at /clls/wloc, and Apple answers with a coordinate list for those radios. iOS then works out its own position from that reply. The module intercepts both directions of that exchange through the proxy's HTTPS decryption and replaces the coordinates with the ones you configured.
The README is explicit about the boundary. This only affects network positioning, meaning Wi-Fi and cell towers. It does not touch the GPS hardware. That distinction decides whether the project is useful to you at all: any app that reads raw GNSS data, or that cross-checks against sensor fusion, will not be fooled by a rewritten WLOC response. The README claims the system treats the result as a real fix, which is why it is harder to detect than a mock-location app, but that claim applies to network positioning specifically.
Who it is for: someone with a supported proxy already installed, comfortable with a CA certificate, who wants a fixed coordinate rather than a moving route. The README's own framing is a beginner tutorial as the entry point, which tells you the intended audience is not the developer who will read location-spoofer.js.
The rewrite pipeline: five proxies, one shared script, and a byte-level fallback
The repository ships one module per proxy platform. Shadowrocket takes ios-location-spoofer.sgmodule, Surge takes the -surge variant, Loon takes a .lnplugin, Quantumult X takes a .snippet, and Stash takes a .stoverride. Four of them point at the same core script, location-spoofer.js; Quantumult X uses location-spoofer-qx.js instead.
The script's job is narrower than it sounds. The README describes a minimal rewrite policy: only latitude, longitude and horizontal accuracy are replaced, while altitude, vertical accuracy and motion state pass through from Apple's original response. No fields are added and no root fields are dropped. The stated reason is defensive. If iOS decides the response is malformed it shows location unavailable, so the module tries to stay inside the shape Apple sent.
Two details make this more than a find-and-replace. First, the module handles cell tower coordinate fields, listed as 22 and 24, not just Wi-Fi hotspot coordinates. Second, it tries to detect the response envelope format (the README names ARPC, synthetic, marker and bare) and, when a beta iOS changes the wrapping enough that known parsers fail, falls back to scanning the raw response bytes for coordinates. That fallback exists to avoid the failure mode where the proxy passes the original data through and the location simply does not change.
There is also a failOpen parameter, default true, which releases the original data on error. That is a deliberate choice: a broken script degrades to a normal, real location rather than to a device that cannot locate itself.
Installing the module and setting your first coordinate
The README's quick start has five steps, and step two is the one people skip. Turn on HTTPS decryption (MITM) in the proxy, install and trust the CA certificate, import the module and enable it, reconnect the VPN and toggle location services, then open a map app to check.
Certificate trust is a separate switch from certificate installation. On iOS it lives under Settings, General, About, Certificate Trust Settings, and the README calls the missing toggle the most common cause of a location that never moves.
The module also needs its MITM hostname list to cover all five domains. If your proxy's decryption list is narrower than the module's, the request is never intercepted. The README lists these:
gs-loc.apple.com
gs-loc-cn.apple.com
gsp-ssl.ls.apple.com
bluedot.is.autonavi.com
bluedot.is.autonavi.com.gds.alibabadns.comThe default target is Apple Park. To change it, edit the module's argument string, where latitude and longitude are the fields that are always rewritten:
latitude=39.9042&longitude=116.4074When nothing changes, the README's diagnostic path is to set debug=true in the same argument string and search the proxy log for "Location spoofer". Seeing a patched wifi or cell line means interception and rewriting both worked, and the remaining problem is the cache described below. A MITM failed line points elsewhere: certificate trust or hostname matching, not the script.
iOS 26 and 27: the cache is the real obstacle
This is the most consequential limitation in the README, and it is not a bug in the module. Starting with iOS 26, Apple strengthened locationd's caching. The system keeps a previous real fix in memory and reuses it for a long time. The script can rewrite the WLOC response successfully, the log can show the patch applied, and the device still reports the old coordinate.
The README's answer is blunt: restart the device. A restart clears the locationd memory cache, and the next WLOC request picks up the modified coordinates. Turning airplane mode on and off, or toggling location services, does not clear it on iOS 26 and later. On iOS 15 through 18, toggling location services is usually enough.
The recommended iOS 26 sequence is therefore more involved than the generic quick start: set the target coordinate first, enable airplane mode, turn off location services, restart the device, then disable airplane mode with Wi-Fi also off, connect the proxy and confirm the VPN icon, turn location services back on, and check the map.
Read that as a cost, not a footnote. If your use case needs a coordinate change in seconds, this project on iOS 26 does not give it to you.
Loon needs more setup than the other four proxies
The Loon plugin carries extra machinery. After importing ios-location-spoofer.lnplugin you open the plugin configuration page under Settings, Plugins, where latitude and longitude can be entered directly. Address search is resolved by a scheduled task that runs every 15 minutes and caches the result, so the README advises entering coordinates directly on first use, or waiting a cron cycle after entering an address.
The plugin also includes a Prepare request script that sets Accept-Encoding: identity, which the README ties to avoiding gzip-related zip decompress errors and script timeouts. If the Loon log shows Evaluate script timeout or zip decompress error:-3, the README's remedy is to update the plugin, reload Loon, and confirm all three scripts (Prepare, Response and the geocode cron) are enabled.
MITM and certificate trust are still required. Address search being asynchronous is the part worth noting: it means the Loon path has a stateful dependency the other modules do not, and a fresh install will not resolve an address immediately.
The optional location-picker server, and why it changes the deployment picture
The base module is a static file with a hardcoded coordinate. The location-picker directory adds a web map where you click a point, and the module reads it through a configUrl. That turns a file edit into a hosted service, which brings its own operational surface.
The self-hosted Node version requires Node 24 or later because it uses the built-in node:sqlite module, and the README notes it still has zero npm dependencies. Tokens, coordinates and access logs live in SQLite in an app.db file next to the DATA_FILE anchor. The TOKEN environment variable is described as bootstrap-only: it seeds the database on first start, and afterwards tokens are created, disabled and deleted in the admin web UI with immediate effect and no redeploy. Multiple tokens can be comma-separated, and each gets its own coordinate.
ADMIN_TOKEN is the other half. If it is unset, the /admin path does not exist at all and returns 404, so the admin surface is opt-in rather than merely protected. The README states it must differ from every user token or the server refuses to start. Port defaults to 8080, and HTTPS only engages when both CERT and KEY are set. Log retention defaults to the last three complete months plus the current month, with TZ_OFFSET_MIN defaulting to 480 minutes (UTC+8).
Alternative hosting paths are listed: a Cloudflare Worker via Wrangler CLI, a Cloudflare web UI variant for people who do not want npm or Wrangler, Railway, plain Node on a VPS or NAS, and Docker. The example remote config URL is https://your-worker.workers.dev/loc.json?token=YOUR_TOKEN. If you only ever want one fixed coordinate, none of this is necessary, and running a server with a database and an admin panel for a single latitude and longitude is overkill.
Licensing, maintenance and what an upgrade costs you
The project is AGPL-3.0. The practical implication is the network clause: if you modify the location-picker server and let other people use it over a network, the AGPL's source-availability obligation is generally understood to apply to that modified version. This is a description of the licence's shape, not legal advice; if you plan to host a modified location-picker for others, read the licence text or ask someone qualified.
The module files themselves are configuration and JavaScript that you import into a proxy, which is a different situation from shipping a modified server, but the same licence covers the repository.
The last push to the default branch was on 2026-09-03, which is recent, and the repository is not archived. That does not tell you anything about release cadence: no releases were retrieved. Upgrades are manual. There is no package manager and no version pinning in what the README shows, so updating means re-importing the module file into your proxy, or pulling the script pointer the module references. The iOS 12 compatible build is a separate module, ios-location-spoofer-ios12.sgmodule, pointing at a script that avoids BigInt because older JavaScriptCore does not support it. There is a test-ios12-compat.js regression test in the repository, but the README does not document a rollback procedure if a new module version breaks your setup, and it does not document version compatibility between module versions and proxy versions beyond the Loon notes.
How this differs from a mock-location app
The obvious alternative is a desktop tool that writes a simulated location to the device over USB, the well-known approach in this space. The difference is architectural rather than a matter of polish. A desktop tool talks to the device directly and can drive the location subsystem at a level that includes GPS, which is why it works for apps that read raw GNSS. It also requires a computer, a cable, and in most cases a developer account or a signed helper application, and the simulated state is usually something you start and stop from the host machine.
ios-location-spoofer inverts all of that. Nothing is installed as an app on the phone. The change happens in the network path, so there is no computer, no cable and no developer account, which is exactly what the README promises. The price is scope: only Wi-Fi and cell-tower positioning is affected, and on iOS 26 and 27 a coordinate change costs a device restart. If you need to move around continuously or need GPS-level fidelity, the desktop approach is the right tool and this one is not. If you need a fixed coordinate on a device you cannot tether to a machine, this is the one that fits.
Editorial conclusion
Adopt it if you already run one of the five supported proxies, can install and trust a CA certificate, and accept that iOS 26 and 27 require a full device restart before a new coordinate shows up. Do not adopt it if you need GPS-level spoofing, if you cannot tolerate a man-in-the-middle certificate on the device, or if you expect a one-tap app. Verify first that the module's five MITM hostnames are present in your proxy's decryption list, and that the certificate trust toggle under Settings, General, About, Certificate Trust Settings is actually on, because the README names that as the most common cause of a location that never changes.
Frequently asked questions
Is there a way to fake your location on an iPhone with ios-location-spoofer?
Yes, by routing Apple's location requests through a proxy that decrypts HTTPS and rewrites the coordinates in the WLOC response. The README states this requires no jailbreak, no computer and no developer account, but it only affects Wi-Fi and cell-tower positioning, not GPS hardware.
How can I change my live location on my iPhone using ios-location-spoofer?
Set latitude and longitude in the module's argument string, then reconnect the VPN and toggle location services. On iOS 26 and 27 the README says you must restart the device, because locationd caches the previous fix and airplane mode or toggling location services will not clear it.
How do I make my iPhone appear in a different location with ios-location-spoofer?
Import the module for your proxy, enable HTTPS decryption, and make sure the five MITM hostnames listed in the README are covered by your decryption list. The default target is Apple Park at 37.3349, -122.00902, and you replace it with your own latitude and longitude.
Is there a way to change your location on an iPhone with ios-location-spoofer?
The module changes what Apple's location service reports for nearby Wi-Fi and cell towers, so iOS computes a different position from the rewritten reply. It does not alter GPS hardware, and the README notes that on iOS 26 and later a device restart is needed before the new coordinate is used.
Community notes