gplaydl-web

August 1, 2026 ยท View on GitHub

Live site: gplaydl.com

gplaydl-web is a server-rendered Go service that downloads APK files from Google Play using a Google account paired through gplaydl-dispenser.

Important: This project uses unofficial Google Play access. Google may flag, lock, or restrict accounts used with it. Please use a separate account and continue at your own risk.

The service does not save APKs. It redirects the browser to an allowlisted Google CDN URL whenever the URL authorizes itself (token-authenticated play.googleapis.com links do, even though Google attaches an optional cookie), and streams without buffering to disk only for gzip-wrapped payloads or hosts where the delivery cookie may genuinely be required.

How it works

  1. The user adds their own Google account in gplaydl Authenticator.
  2. The browser exchanges a one-time pairing code for a dispenser API key.
  3. The API key is stored in an authenticated, encrypted, HTTP-only cookie.
  4. The service asks the dispenser for a short-lived Play token and calls Google Play's details, purchase, and delivery endpoints.
  5. Delivery manifests are cached in memory for one hour by default. Users can request a fresh link from the advanced form control.

Cache entries are isolated by a hash of the pairing key, package, locale, and device profile. Tokens, API keys, cookies, and CDN capability URLs are not logged.

Local development

Go 1.26 or newer is required.

cp .env.example .env
export PUBLIC_URL=http://localhost:8081
export SESSION_KEY="$(openssl rand -base64 32)"
go run ./cmd/gplaydl-web

The service listens on 127.0.0.1:8081 by default. Environment files are not loaded automatically; export them or use your process supervisor.

Configuration:

  • GPLAYDL_ADDR: listen address.
  • PUBLIC_URL: canonical external origin.
  • DISPENSER_URL: HTTPS dispenser origin.
  • SESSION_KEY: base64-encoded 32-byte AES key; required for HTTPS deployments.
  • CACHE_ENABLED: enables the in-memory manifest cache.
  • CACHE_TTL: manifest lifetime, default 1h.
  • CACHE_MAX_ENTRIES: bounded cache size, default 1000.
  • UPSTREAM_TIMEOUT: response-header timeout, default 30s.

Verification

gofmt -w .
go vet ./...
go test -race ./...
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -trimpath ./cmd/gplaydl-web

Tests cover protobuf decoding, cache isolation and bypass, encrypted session tamper resistance, and CDN host validation.

Deployment

The files in deploy install the binary as a hardened systemd service on 127.0.0.1:8081 and proxy gplaydl.com through Caddy. The GitHub Actions workflow builds a static Linux/amd64 binary and supports atomic deployment with health checks and rollback.

Production requires a unique SESSION_KEY. Restrict the deployment user to writing /opt/gplaydl-web and restarting only gplaydl-web; Caddy and initial systemd installation should remain administrator-controlled.

Important limitations

  • This is an unofficial Google Play client and is not affiliated with Google.
  • Google can change its private Play protocol without notice.
  • Availability depends on the paired account, region, and selected Android device profile. Paid or unacquired apps may not be downloadable.
  • Split APK apps require the base APK and all relevant configuration splits.
  • The user is responsible for the downloaded app's license and publisher terms.
  • Unofficial clients can trigger account security checks or restrictions; a separate account without payment methods is advisable.