Created
October 14, 2026 07:50
-
-
Save Reelix/f46504e754b549558f50dc37c9f3fe0a to your computer and use it in GitHub Desktop.
Download IPA from Firebase given Firebase itms-services:// link
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| import os | |
| import re | |
| import sys | |
| import urllib.parse | |
| import urllib.request | |
| def extract_app_info(raw_link: str): | |
| # Unquote the outer layer to expose query parameters | |
| unquoted = urllib.parse.unquote(raw_link) | |
| # Get the display name | |
| name_match = re.search(r'[?&]display_name=([^&]+)', unquoted) | |
| raw_name = name_match.group(1) if name_match else "app" | |
| clean_name = re.sub(r'[\\/*?:"<>|]', "", raw_name).strip() | |
| filename = f"{clean_name}.ipa" | |
| # Get the direct download link | |
| uri_match = re.search(r'[?&]download_uri=(https?://[^&]+)', unquoted) | |
| if not uri_match: | |
| raise ValueError("Could not find 'download_uri' in the provided link.") | |
| # Second unquote decodes the inner token parameters (%253D -> %3D -> =) | |
| curl_link = urllib.parse.unquote(uri_match.group(1)) | |
| return filename, curl_link | |
| def download_ipa(url: str, output_filename: str): | |
| # Stream the IPA directly to disk | |
| req = urllib.request.Request(url, headers={"User-Agent": "curl/7.88.1"}) | |
| with urllib.request.urlopen(req) as response, open(output_filename, "wb") as f: | |
| total_size = response.getheader("Content-Length") | |
| total_size = int(total_size) if total_size else None | |
| downloaded = 0 | |
| chunk_size = 1024 * 1024 # 1 MB | |
| while True: | |
| chunk = response.read(chunk_size) | |
| if not chunk: | |
| break | |
| downloaded += len(chunk) | |
| f.write(chunk) | |
| if total_size: | |
| pct = (downloaded / total_size) * 100 | |
| mb = downloaded / (1024 * 1024) | |
| total_mb = total_size / (1024 * 1024) | |
| sys.stdout.write(f"\rDownloading: {pct:5.1f}% [{mb:6.1f} / {total_mb:6.1f} MB]") | |
| else: | |
| mb = downloaded / (1024 * 1024) | |
| sys.stdout.write(f"\rDownloading: {mb:6.1f} MB") | |
| sys.stdout.flush() | |
| print(f"\nDone! File saved as: {output_filename}") | |
| def main(): | |
| raw_link = sys.argv[1] if len(sys.argv) > 1 else input("Enter URL: ").strip() | |
| try: | |
| filename, curl_link = extract_app_info(raw_link) | |
| print(f"\n[1] App Name : {filename}") | |
| print(f"[2] Direct URL: {curl_link}\n") | |
| print(f"[3] Downloading {filename}...") | |
| download_ipa(curl_link, filename) | |
| except Exception as e: | |
| print(f"Error: {e}") | |
| sys.exit(1) | |
| if __name__ == "__main__": | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment