- Rust 100%
|
|
||
|---|---|---|
| src | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| LICENSE | ||
| README.md | ||
gplay-dl
Google Play package download and archival tool.
Warning: Usage of this program is against the Google ToS. Your account can be banned. I have been successfully using it without issues, and a similar project that also interfaces with Google Play in ToS breaking ways called Aurora Store has a sizable user base, but there's no guarantees. Avoid using with your primary account if possible, and in case you get banned, don't blame it on me. I warned you.
Keep in mind this project is currently in it's early stages. It can already download packages, but it might break, and it's not easy to use.
Setup
Download the latest build for your OS from Releases. Move the executable (gplay-dl or gplay-dl.exe on Windows) to a directory on your PATH.
Basic usage
Configuration file
Create a config.toml file holding the program configuration. An example config.toml can look like this:
check_delay = 10000
[authentication]
email = "example@example.com"
aas_token = ""
[download]
locale = "en"
download_devices = ["px_9a"]
target_directory = "{package}/{version}"
skip_existing = true
lax = false
Configuration overview:
-
check_delay(integer): Time in miliseconds to wait between checks using thecheck-versionscommand. -
authentication.email(string): E-mail address tied to the authenticated Google account. -
authentication.aas_token(string): Authentication token. -
download.locale(string): Locale string. See Advanced downloading section. -
download.download_devices(string array): Device set. See Advanced downloading section. -
download.target_directory(string): Directory to download package files to.{package}is replaced with the package ID, and{version}is replaced with the version code. -
download.skip_existing(bool): Skip existing files rather than overwriting them. -
download.lax(bool): Don't error out of a download if one device fails to get version info. This is not recommended, as you might miss downloads if something goes wrong, but you'll still get a warning.
Authentication
Change authentication.email in config.toml to your Google account e-mail address. Go to the embedded Google sign in page, and log in with the same address. When you sign in and the page continues to load infinitely, use your browser's devtools to grab the oauth_token cookie.
Now, generate an aas token by running the login command.
gplay-dl login token
Where token is the value of the cookie.
It should output something like this:
Some("aas_et/...")
Copy everything in between the quotes and paste it into config.toml as authentication.aas_token.
Checking if everything works
Run the following command:
gplay-dl check-versions moe.low.arc 1208210 1208210
If it outputs the following, everything should be set up properly:
Trying 1208210...
1208210
Downloading
Provided you have an appropriate device set, you can download all files associated with a package using the download command.
gplay-dl download package [version ...]
Where package is the package ID to download, and version is the version code. You can provide more than one version code. Not providing a version code downloads the latest version of the package.
The device set given in the example configuration should be able to download files required to run the program on an ARM64 device. If this is not enough, read the Advanced downloading section.
Advanced downloading
Devices
Google Play is complicated. It's not possible to simply ask for "all files of a package". Instead, the client provides information about itself (Android version, architecture, locale, model number etc.), and the server decides which files to serve (it also decides what is treated as the latest version).
Because of this, gplay-dl uses a device set system - you can provide a set of devices, and it will ask Google Play to provide a download for each one, getting all available files. An appropriate device set needs to be constructed for each package (sometimes even version) - asking for downloads for many devices would take too much time, abuse the Google Play API, which could lead to ratelimiting or account bans, as well as still not be guaranteed to get all available files.
gplay-dl has some built-in devices. Those are identified by string IDs, such as px_9a. If you have a device config file in Aurora Store format, you can provide it by specifying a path prefixed with *, like *mydevice.properties or */home/user/devices/mydevice.properties.
You can list all available built-in devices with the devices command.
gplay-dl devices
You can modify devices by adding options in the form:
device[:option=value[,option=value ...]]
Available options:
architectures: Changes the available architectures. The value is a;-separated list of architecture identifiers. See https://developer.android.com/ndk/guides/abis.density: Changes the DPI. The value is the DPI as an integer. See https://developer.android.com/training/multiscreen/screendensities.
For example, rm_7:architectures=armeabi-v7a;x86_64,density=120 is a Xiaomi Redmi 7 with ARMv7 and x86-64 architectures and 120 DPI (ldpi).
Google Play will reject modified devices in some cases, in which case the modifications will have no effect.
Package files
First, we need to talk about what files we might want to download. There's a bunch of them.
As you might know, the file format used for Android packages is APK. An APK can be full or split.
Full APKs are what most people are familiar with, you have one file, which can be installed by opening it with the package installer on your device. Depending on the package, they can come with corresponding OBB files.
Split APKs are the more modern way to distribute packages - they come in groups, and the entire group (or a subset of it) has to be installed at once, which requires more complicated methods. That's because the functionality is split between multiple APK files, allowing you to only download and install the ones your device needs. This is not a bad thing, since the package takes up less space after installation, but Google Play makes downloading split APKs more complex.
They can be divided into the following categories:
| Name | Downloaded | Filename | Number in package |
|---|---|---|---|
| Base | Always | base.apk | 1 |
| Architecture | Depending on supported and primary instruction sets | config.architecture.apk | 0-4 |
| DPI | Depending on display DPI | config.prefixdpi.apk | 0-7 |
| Locale | Depending on current locale | config.locale code.apk | 0+ (usually 0 or a few dozen) |
| Custom | Either always or depending on the device | name.apk | 0+ (usually 0 or 1) |
Custom splits are often used as a way to separate assets. They are rarely used, notably by some Google Pixel packages, as a way to install device-specific functionality.
Full APKs used to be the only way packages are distributed, but nowadays an overwhelming amount of packages on Google Play comes as split APKs.
Versions with split APKs may also have a full APK available for certain devices. This used to be true for all packages, but it is no longer the case - the full APKs of these versions were for all intents and purposes completely removed from Google Play.
Constructing a device set
First, investigate what files are available for the package and version you are trying to download. To do this, use the check-devices command.
gplay-dl check-devices package [version] [device ...]
Where package is the package ID, version is the version code and device is the device to check. Not providing a version code checks the latest version for a given device. You can provide more than one device, not providing a device checks all built in devices.
This gives an output like the following:
device: px_9a, version code: 1209270, split apks: (arcassets, config.arm64_v8a, config.en, config.xxhdpi), data files: ()
device: rm_5i, login error: Error { kind: Other(Error { kind: TermsOfService }) }
device: waydroid, download error: Error { kind: InvalidApp }
device: rm_5_pro, version code: 1209270, split apks: (arcassets, config.armeabi_v7a, config.en, config.xxhdpi), data files: ()
device: px_tablet, version code: 142, split apks: (), data files: (main.142.com.PigeonGames.Phigros.obb, patch.142.com.PigeonGames.Phigros.obb)
Each line represents a device, and is split by commas into sections. The device section is the device identifier. If a login error or download error section is present, then this device failed to download the package and can be ignored. For all the other devices, which we'll call supported devices (usually a failed download means the device is unsupported), see if the split apks section is empty or not - if it's empty, this version has a full APK, if it's not - it has split APKs.
If there's a device that has a full APK, add the device to the set. If the data files section is not empty, the download will contain an OBB file as well.
If there are devices that have split APKs, consider each unique split found in the split apks sections of all these devices. Since the base split (not shown in split apks) and asset splits are always downloaded, we do not need to worry about them - as long as one supported device is in the set, it will be downloaded. Now, add a device for each unique architecture, DPI and custom split to the set.
Try to make device sets as small as possible, as that reduces the amount of required requests to Google Play.
Locales
Locale splits are not part of the device set construction process, because a single device can easily download all possible locale splits. If a version has one or more locale split in the split apks section, then we can know that at least those splits are available, but it's usually more than that. Sadly, there's no perfect way to guess what locale splits are available. One method includes using the output of aapt dump badging on an older full APK.
Once you have a list of locale splits to download, set the download.locale string to a comma separated list of locales.
Versions
All Android packages have a version code. It is a positive integer unique to each version of a package. A larger number means a newer version. The version code is manually assigned by the developer when building the package.
Google Play keeps all released versions for a package, meaning you can download any past version of a package at any time if you provide a version code. The issue is, there is no way to ask Google Play for all version codes for a package.
To obtain a version code you don't know, you need to more or less guess. A lot of developers simply start at 1 and increase the number by 1 for each released version. Sometimes, it's a more complex scheme, possibly one that is seemingly random, or maybe it is just random.
gplay-dl does offer a way to simplify the process of searching for version codes. If you need to check which versions exist given a range, you can use the check-versions command to try them by brute force.
gplay-dl check-versions package version first version last
Where package is the package ID, version first is the first version code to check, and version last is the last version code to check.
Region locking
Certain packages can only be downloaded from certain regions. As far as tested, to get a package locked to a certain region, the following needs to be done from (ie. with an IP address located in) that region:
- Creating the Google account (you can also switch an existing one to that region, but this is annoying).
- Logging into the Google account.
- "Purchasing" the package. For free packages, this means starting a download once (running
check-devicesis enough).
Downloads of any version of already purchased packages can seemingly be done from any region.
Copyright
Copyright © 2024-2026 Grzesiek11
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.