Spotify pi Parameter
Spotify Share Links and the pi Parameter: A Privacy Research Analysis
https://open.spotify.com/playlist/487jKTFqWhs6b0AEUz0WpX?si=0FGqTuRNTq2BJZeCP------&pi=g-k1ZIqMToS--
Every Spotify share link contains two query parameters: si and pi. The si is documented — Spotify uses it to build social graphs. The pi is not. In recent months, a claim has been circulating on Telegram and Discord — amplified by AI-generated OSINT guides spreading across Italian, Dutch, German, and UK communities — that pi stands for Profile Identifier and directly exposes the Spotify account of whoever shared the link.
I tested that claim empirically.
Static Analysis of the pi Value
The string g-k1ZIqMToS-- decomposes into a g- prefix and an 11-character body in base64url alphabet, decoding to 8 raw bytes (64 bits).
| Identifier | Length | Decoded size | Consistent with |
|---|---|---|---|
si | 22 char | 16 bytes (128-bit) | Random session token / GUID |
pi body | 11 char | 8 bytes (64-bit) | Short opaque token |
| Canonical Spotify user ID | 28 char | base62 lowercase | Documented user URI format |
64 bits is too small for a globally unique identifier on a platform with hundreds of millions of accounts. The structure also does not match canonical Spotify user IDs, which are 22–28 characters of lowercase base62. The g- prefix is claimed by informal sources to indicate Google OAuth registration — there is no evidence for this.
Testing Resolvability: Five Surfaces, One Control
Each test used a control: the canonical user ID 31squddjtl7ycsxqzqfjnx------, confirmed valid via the music:creator meta tag of the share page. If the control passes and pi fails, the conclusion is clear.
GET /user/g-k1ZIqMToS-- returns 404. Control returns 200. pi fails.
The pi persists in og:url and deeplinks, but the only user URI exposed is the playlist owner, not any account linked to pi. pi fails.
Both flows returned 403 for both target and control. Since November 2024, Spotify restricted API access for development-mode apps uniformly — not selectively on pi. Non-discriminating by design.
spotify:user:g-k1ZIqMToS-- returns “Couldn’t find that”. Control opens the correct profile. pi fails.
| Surface | pi | Control | Discriminating? |
|---|---|---|---|
Web resolver /user/{id} | 404 | 200 | Yes — pi fails |
| Share page metadata | no user ref | — | Yes — pi fails |
| Web API (both flows) | 403 | 403 | No — endpoint closed |
| Desktop deeplink | not found | profile opens | Yes — pi fails |
What pi Is (Most Likely)
Based on structural and behavioral analysis — not source code access — the most consistent hypothesis is that pi is an opaque playback or share context token: a short-lived identifier Spotify uses internally to attribute plays or share events to a specific context. This explains why it persists in deeplinks while si is dropped from og:url: Spotify preserves playback attribution when the link is opened via the app, without exposing any user identity.
The Real Privacy Issue: the si Parameter
The si parameter is the actual concern. Since the Spotify Messages rollout in late 2025, Spotify uses si to retroactively populate “suggested friends” from years of share history. Sharing a playlist on Telegram or Discord two years ago is enough for Spotify to surface that connection today.
Mitigations: the Firefox extension “Remove Spotify Tracker Parameters”, Brave Browser’s built-in clean link copy, or simply deleting everything after ? before sharing.
Python Sanitizer: Strip Spotify Tracking Parameters
#!/usr/bin/env python3
"""
spotify_link_sanitize.py -- strips si, pi, and all query params from Spotify share links.
Usage: python spotify_link_sanitize.py "https://open.spotify.com/playlist/...?si=...&pi=..."
"""
import sys
from urllib.parse import urlparse, urlunparse
SPOTIFY_HOSTS = {"open.spotify.com", "spotify.link"}
def sanitize(url):
p = urlparse(url.strip())
if p.netloc.lower() not in SPOTIFY_HOSTS:
raise ValueError(f"Not a Spotify URL: {p.netloc}")
removed = dict(kv.partition("=")[::2] for kv in p.query.split("&")) if p.query else {}
clean = urlunparse((p.scheme, p.netloc, p.path.rstrip("/"), "", "", ""))
return clean, removed
if __name__ == "__main__":
clean, removed = sanitize(sys.argv[1])
print(clean)
if removed:
print("Removed:", ", ".join(
f"{k}={v[:20]}..." if len(v) > 20 else f"{k}={v}"
for k, v in removed.items()
), file=sys.stderr)
Conclusion
The claim that pi in Spotify share links exposes the sender’s account is not supported by empirical evidence. Three independent public surfaces that resolve canonical Spotify user IDs do not resolve pi. The parameter is real, undocumented, and persistent — but it is not a user identifier on any publicly reachable surface.
If you found this technique in an AI-generated OSINT guide or a Telegram channel, it does not hold up under testing.
? — the link works identically.