Build scripts that cross-compile Python 3 for Android devices.
Currently targeting Python 3.13.11.
Building requires:
- Linux (other platforms supported by NDK may work but are not tested)
- Android NDK r19 or above. Set
$ANDROID_NDKto its root directory. Tested with NDK r26.2 (26.2.11394342). ticbinary from ncurses on the building host (for terminfo generation)- A case-sensitive filesystem. The default filesystem on Windows and macOS is case-insensitive and building may fail.
curl,patch,make,gccon the building host
Note: A matching-version Python on the host is not required. The build script automatically compiles a native Python of the same version from source and uses it as the cross-compilation build-python.
Running requires:
- Android 5.0 (Lollipop, API 21) or above
- Architecture:
arm,arm64,x86, orx86_64
./clean.sh
ARCH=arm64 ANDROID_API=21 ANDROID_NDK=/path/to/ndk ./build.shSupported ARCH values: arm, arm64, x86, x86_64
The build proceeds in the following steps:
- Download Python source if not already present in
src/ - Copy the
Android/build scripts into the source tree - Apply
unversioned-libpython.patchif needed (skipped on Python 3.13+ which already includes the fix) - Build a native Python of the same version into
native_python/(reused on subsequent builds if already present) - Build Android dependencies (bzip2, gdbm, libffi, libuuid, ncurses,
openssl, readline, sqlite, xz, zlib) into
Android/sysroot/ - Configure and build Python for Android
- Install into
build/ - Remove files not needed at runtime:
test/,idlelib/,config-*/,libpython*.a, and the accidental ensurepip path - Strip debug symbols from ELF binaries and
.sofiles using NDKllvm-strip
Output is placed in build/. A typical build produces ~80 MB after cleanup
and stripping (down from ~370 MB before).
Download the latest NDK for Linux from https://developer.android.com/ndk/downloads and extract it.
docker run --rm -it \
-v $(pwd):/python3-android \
-v /path/to/android-ndk:/android-ndk:ro \
--env ARCH=arm64 \
--env ANDROID_API=21 \
python:3.13-slim \
/python3-android/docker-build.shPodman is also supported. Simply replace docker with podman.
- Make sure
adb shellworks - Copy all files in
build/to a folder on the device (e.g.,/data/local/tmp/python3). Note that/sdcardis not a POSIX-compliant filesystem; the Python binary will not run from there. - In
adb shell:
cd /data/local/tmp/python3
. ./env.sh
python3Android uses the old certificate naming scheme while OpenSSL uses the new one.
If you get CERTIFICATE_VERIFY_FAILED, collect system certificates:
cd /data/local/tmp/python3
mkdir -p etc/ssl
cat /system/etc/security/cacerts/* > etc/ssl/cert.pemThe certificate path may vary by device vendor and Android version. Root access is required to collect user-installed certificates.
Verify SSL/TLS:
import urllib.request
print(urllib.request.urlopen('https://httpbin.org/ip').read().decode('ascii'))./clean.shThis removes src/, build/, native_build/, and native_python/.
To preserve the native Python build across clean cycles (saves significant
build time), remove native_build and native_python from clean.sh.
- Python 3.13.11 cannot be cross-compiled using a host Python 3.13.0 binary
due to an internal API change in
linecache._register_codebetween those versions. The build script works around this by building a native Python 3.13.11 from source automatically. - The
unversioned-libpython.patchis a no-op on Python 3.13+ (the fix is already included upstream). The build script skips it gracefully.