A blazing-fast, lightweight, and user-friendly tool built with Go for retrieving app information from major app stores.
- ⚡️ Blazingly fast — Lightning-quick app data retrieval powered by Go
- 🛍️ Multi-store support — Fetch data from major app stores in one place
- 🪶 Lightweight — Minimal resource footprint for efficient operation
- 🐳 Containerized — Full Docker support for flexible deployment
- 🔌 Simple API — Clean REST endpoints for seamless integration
- 📝 Structured data — Consistent JSON output for all app stores
- 🛠️ Easy setup — Get started in minutes with straightforward configuration
Katsini comes with Chrome bundled in the container - no separate services or configuration needed!
docker run -p 8080:8080 ghcr.io/arisecode/katsini:latest🎉 That's it! You can now access the service at http://localhost:8080
Note: Chrome is automatically bundled with anti-bot protection. Just run the single container and you're ready to go!
- URL:
http://localhost:8080/playstore - Method:
GET - Query Parameter:
bundleId(REQUIRED): The app package name (e.g.,com.mediocre.dirac).lang(optional, defaults to `'en'): The two letter language code in which to fetch the app page.country(optional, defaults to 'us'): The two letter country code used to retrieve the applications. Needed when the app is available only in some countries.
curl http://localhost:8080/playstore?bundleId=com.mediocre.dirac&lang=en&country=us{
"bundleId": "com.mediocre.dirac",
"developer": "Mediocre",
"title": "Beyondium",
"updated": "31-10-2019",
"url": "https://play.google.com/store/apps/details?id=com.mediocre.dirac&hl=en&gl=us",
"version": "1.1.5"
}- URL:
http://localhost:8080/appstore - Method:
GET - Query Parameter:
appIdorbundleId(REQUIRED):appId: The unique identifier for the application in the Apple App Store. This can be found in the app's store URL after the/id<APP_ID>segment.bundleId: The app package name (e.g.,com.thinkdivergent).
country(optional, defaults to 'us'): The two letter country code used to retrieve the applications. Needed when the app is available only in some countries.
curl http://localhost:8080/appstore?appId=1592213654&country=us{
"appId": "1592213654",
"bundleId": "com.thinkdivergent",
"developer": "Think Divergent LLC",
"title": "Think Divergent",
"updated": "11-02-2023",
"url": "https://apps.apple.com/us/app/think-divergent/id1592213654?uo=4",
"version": "2.0.13"
}- URL:
http://localhost:8080/appgallery - Method:
GET - Query Parameter:
appId(REQUIRED): The unique identifier for the application in the Huawei AppGallery. This can be found in the app's store URL after the/app/C<APP_ID>segment.
Huawei AppGallery actively blocks requests from datacenter/VPS IP addresses, returning empty pages even though the app exists. If you're deploying on a VPS (AWS, DigitalOcean, Vultr, etc.) and experiencing issues where apps return empty results or "app not found" errors, you must configure the API fallback:
- Register at Huawei Developer Console
- Create an app/project and enable AppGallery Publishing API
- Get your OAuth2 credentials (Client ID and Client Secret)
- Set environment variables:
docker run -p 8080:8080 \ -e HUAWEI_CLIENT_ID="your_client_id" \ -e HUAWEI_CLIENT_SECRET="your_client_secret" \ ghcr.io/arisecode/katsini:latest
The application will automatically fallback to the official Huawei API when scraping fails, bypassing IP restrictions.
curl http://localhost:8080/appgallery?appId=100102149{
"appId": "100102149",
"bundleId": "com.radio.fmradio",
"developer": "RADIOFM",
"title": "Radio FM",
"updated": "05-11-2024",
"url": "https://appgallery.huawei.com/app/C100102149",
"version": "6.5.6"
}The benchmarks were run using the following command:
go test -bench=. -benchtime=1s -benchmem -cpu=1The results of the benchmarks are as follows:
goos: linux
goarch: amd64
pkg: github.com/arisecode/katsini
cpu: 12th Gen Intel(R) Core(TM) i7-12700
BenchmarkGooglePlayStore 2 811015314 ns/op 3816876 B/op 21807 allocs/op
BenchmarkAppleAppStore 64 18702830 ns/op 95091 B/op 163 allocs/op
BenchmarkHuaweiAppGallery 2 892189872 ns/op 2685124 B/op 15531 allocs/opThe benchmark results show the average time taken and how many iterations were run per operation can be done in a second.
- Note: The benchmarks were run on a 12th Gen Intel(R) Core(TM) i7-12700 CPU and using a single CPU core.
2: The number of iterations run per operation.ns/op: The average time taken for each operation.B/op: The average number of bytes allocated per operation.allocs/op: The average number of memory allocations per operation.
Katsini uses chromedp-undetected to bypass basic anti-bot detection mechanisms. This helps ensure reliable data fetching from app stores that implement bot protection.
Features:
- 🛡️ Automatic stealth mode when available
- 🔄 Graceful fallback to regular chromedp on unsupported platforms
- 🤖 Mimics real browser behavior to avoid detection
- ⚡ No performance impact on regular operations
Note: The undetected mode works best in Linux environments with headless Chrome. On macOS and other platforms, it automatically falls back to standard chromedp mode.
Here are some of the libraries that are used in this project:
- Chromedp - A faster, simpler way to drive browsers in Go.
- chromedp-undetected - Anti-bot detection bypass for chromedp.
