playfast


Nameplayfast JSON
Version 0.4.0 PyPI version JSON
download
home_pageNone
SummaryPlayfast - Lightning-Fast Google Play Store Scraper
upload_time2025-10-14 12:53:02
maintainerNone
docs_urlNone
authorNone
requires_python>=3.11
licenseMIT
keywords google-play scraper async rust pyo3 performance free-threading
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Playfast โšก

> Lightning-Fast Google Play Store Scraper

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
[![Built with Rust](https://img.shields.io/badge/built%20with-Rust-orange.svg)](https://www.rust-lang.org/)
[![CI](https://github.com/mixL1nk/playfast/actions/workflows/ci.yml/badge.svg)](https://github.com/mixL1nk/playfast/actions/workflows/ci.yml)
[![Coverage](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/mixL1nk/6a5cda65b343fffe18719b3a9d6d6a3b/raw/playfast-coverage.json)](https://github.com/mixL1nk/playfast/actions/workflows/ci.yml)
[![PyPI](https://img.shields.io/pypi/v/playfast?logo=python)](https://pypi.org/project/playfast/)
[![Documentation](https://img.shields.io/badge/docs-mkdocs-blue)](https://mixL1nk.github.io/playfast/)

Playfast is a high-performance Google Play Store scraper built with **Rust + PyO3**, delivering **5-10x faster performance** with true parallel batch processing.

## โœจ Features

- ๐Ÿš€ **Blazingly Fast**: Batch API is 5-10x faster than sequential
- โšก **True Parallel**: Rust core completely releases GIL
- ๐Ÿฆ€ **Pure Rust**: HTTP + parsing all in Rust for maximum performance
- ๐Ÿ”’ **Type Safe**: Full Pydantic validation and type hints
- ๐Ÿ’พ **Memory Efficient**: Only 1.5 KB per app, linear scaling
- ๐ŸŒ **Multi-Country**: 247 countries, 93 unique Play Stores
- ๐Ÿ“ฆ **Batch API**: High-level functions for easy parallel processing

## ๐Ÿ“Š Performance

**Batch Processing** makes bulk operations **5-10x faster** through true Rust parallelism!

| Method                   | Time    | Speedup     |
| ------------------------ | ------- | ----------- |
| **Batch API**            | **~3s** | **6-8x** ๐Ÿš€ |
| RustClient + ThreadPool  | ~3-4s   | 6-7x        |
| AsyncClient (concurrent) | ~3-5s   | 5-7x        |
| Sequential               | ~20-30s | 1x          |

*Benchmark: Fetching 3 apps across 3 countries (9 requests total)*

## ๐Ÿš€ Quick Start

### Installation

```bash
pip install playfast
```

### Option 1: Batch API (Recommended - Easiest & Fastest)

```python
from playfast import fetch_apps

# Fetch multiple apps across countries (parallel!)
apps = fetch_apps(
    app_ids=["com.spotify.music", "com.netflix.mediaclient"],
    countries=["us", "kr", "jp"],
)
print(f"Fetched {len(apps)} apps in ~3 seconds!")
```

### Option 2: RustClient (Maximum Performance)

```python
from playfast import RustClient

client = RustClient()

# Get app information (GIL-free!)
app = client.get_app("com.spotify.music")
print(f"{app.title}: {app.score}โญ ({app.ratings:,} ratings)")

# Get reviews
reviews, next_token = client.get_reviews("com.spotify.music")
for review in reviews[:5]:
    print(f"{review.user_name}: {review.score}โญ")
```

### Option 3: AsyncClient (Easy Async)

```python
import asyncio
from playfast import AsyncClient


async def main():
    async with AsyncClient() as client:
        app = await client.get_app("com.spotify.music")
        print(f"{app.title}: {app.score}โญ")


asyncio.run(main())
```

## ๐Ÿ“š Examples

See the [`examples/`](examples/) directory for more:

- [`01_async_client.py`](examples/01_async_client.py) - AsyncClient basics
- [`02_rust_client.py`](examples/02_rust_client.py) - RustClient for max performance
- [`03_batch_api.py`](examples/03_batch_api.py) - High-level batch API
- [`04_countries_and_categories.py`](examples/04_countries_and_categories.py) - Country optimization

## ๐Ÿ“– Documentation

- **[Getting Started](docs/getting_started.md)** - Installation and first steps
- **[Quick Start](docs/quick_start.md)** - Practical examples
- **[API Reference](docs/api/)** - Complete API documentation
- **[Batch API Guide](docs/BATCH_API.md)** - Batch processing guide

## ๐Ÿ—๏ธ Architecture

Playfast uses **pure Rust** for both HTTP and parsing:

```bash
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚   Python Layer                      โ”‚
โ”‚   - Batch API (high-level)          โ”‚
โ”‚   - RustClient / AsyncClient        โ”‚
โ”‚   - Pydantic Models                 โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
               โ”‚ PyO3 Bindings
               โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚   Rust Core                         โ”‚
โ”‚   - HTTP Client (reqwest)           โ”‚
โ”‚   - HTML Parser (scraper)           โ”‚
โ”‚   - Parallel Processing (rayon)     โ”‚
โ”‚   - Complete GIL Release            โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
```

### Three Client Options

| Method          | Speed  | Ease   | Best For       |
| --------------- | ------ | ------ | -------------- |
| **Batch API**   | โšกโšกโšก | โญโญโญ | Multiple items |
| **RustClient**  | โšกโšกโšก | โญโญ   | Single items   |
| **AsyncClient** | โšกโšก   | โญโญ   | Async code     |

## ๐ŸŒ Multi-Country Optimization

Playfast optimizes global data collection:

```python
from playfast import get_unique_countries, get_representative_country

# Instead of 247 countries, use 93 unique stores (2.7x faster!)
unique = get_unique_countries()  # 93 unique Play Stores

# Get representative for any country
rep = get_representative_country(
    "fi"
)  # Finland โ†’ Vanuatu store (shared by 138 countries)
```

## ๐Ÿ”ง Development

```bash
# Clone repository
git clone https://github.com/mixL1nk/playfast.git
cd playfast

# Install dependencies
uv sync

# Build Rust extension
uv run maturin develop --release

# Run tests
uv run pytest

# Run examples
uv run python examples/basic.py

# Run benchmarks
uv run python benchmarks/batch_apps_benchmark.py
```

See [Development Setup](docs/development/setup.md) for detailed instructions.

## ๐Ÿค Contributing

Contributions are welcome! Please:

1. Fork the repository
1. Create a feature branch
1. Make your changes
1. Add tests
1. Submit a pull request

## ๐Ÿ“ License

MIT License - see [LICENSE](LICENSE) for details.

## ๐Ÿ™ Acknowledgments

- Built with [PyO3](https://github.com/PyO3/pyo3) (Rust-Python bindings)
- Inspired by [google-play-scraper](https://github.com/facundoolano/google-play-scraper)
- HTTP: [reqwest](https://github.com/seanmonstar/reqwest)
- Parsing: [scraper](https://github.com/causal-agent/scraper)

## โš ๏ธ Disclaimer

This tool is for educational and research purposes only. Please respect Google Play Store's Terms of Service. Use responsibly with appropriate rate limiting.

______________________________________________________________________

**Made with โค๏ธ using Rust + Python**


            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "playfast",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.11",
    "maintainer_email": null,
    "keywords": "google-play, scraper, async, rust, pyo3, performance, free-threading",
    "author": null,
    "author_email": "Taeyun Jang <taeyun16@pm.me>",
    "download_url": "https://files.pythonhosted.org/packages/41/ef/6b2635214f1a4b9160d0c7634307e685a9ea7494345937c1dfcf2ef0bb0e/playfast-0.4.0.tar.gz",
    "platform": null,
    "description": "# Playfast \u26a1\n\n> Lightning-Fast Google Play Store Scraper\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)\n[![Built with Rust](https://img.shields.io/badge/built%20with-Rust-orange.svg)](https://www.rust-lang.org/)\n[![CI](https://github.com/mixL1nk/playfast/actions/workflows/ci.yml/badge.svg)](https://github.com/mixL1nk/playfast/actions/workflows/ci.yml)\n[![Coverage](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/mixL1nk/6a5cda65b343fffe18719b3a9d6d6a3b/raw/playfast-coverage.json)](https://github.com/mixL1nk/playfast/actions/workflows/ci.yml)\n[![PyPI](https://img.shields.io/pypi/v/playfast?logo=python)](https://pypi.org/project/playfast/)\n[![Documentation](https://img.shields.io/badge/docs-mkdocs-blue)](https://mixL1nk.github.io/playfast/)\n\nPlayfast is a high-performance Google Play Store scraper built with **Rust + PyO3**, delivering **5-10x faster performance** with true parallel batch processing.\n\n## \u2728 Features\n\n- \ud83d\ude80 **Blazingly Fast**: Batch API is 5-10x faster than sequential\n- \u26a1 **True Parallel**: Rust core completely releases GIL\n- \ud83e\udd80 **Pure Rust**: HTTP + parsing all in Rust for maximum performance\n- \ud83d\udd12 **Type Safe**: Full Pydantic validation and type hints\n- \ud83d\udcbe **Memory Efficient**: Only 1.5 KB per app, linear scaling\n- \ud83c\udf0d **Multi-Country**: 247 countries, 93 unique Play Stores\n- \ud83d\udce6 **Batch API**: High-level functions for easy parallel processing\n\n## \ud83d\udcca Performance\n\n**Batch Processing** makes bulk operations **5-10x faster** through true Rust parallelism!\n\n| Method                   | Time    | Speedup     |\n| ------------------------ | ------- | ----------- |\n| **Batch API**            | **~3s** | **6-8x** \ud83d\ude80 |\n| RustClient + ThreadPool  | ~3-4s   | 6-7x        |\n| AsyncClient (concurrent) | ~3-5s   | 5-7x        |\n| Sequential               | ~20-30s | 1x          |\n\n*Benchmark: Fetching 3 apps across 3 countries (9 requests total)*\n\n## \ud83d\ude80 Quick Start\n\n### Installation\n\n```bash\npip install playfast\n```\n\n### Option 1: Batch API (Recommended - Easiest & Fastest)\n\n```python\nfrom playfast import fetch_apps\n\n# Fetch multiple apps across countries (parallel!)\napps = fetch_apps(\n    app_ids=[\"com.spotify.music\", \"com.netflix.mediaclient\"],\n    countries=[\"us\", \"kr\", \"jp\"],\n)\nprint(f\"Fetched {len(apps)} apps in ~3 seconds!\")\n```\n\n### Option 2: RustClient (Maximum Performance)\n\n```python\nfrom playfast import RustClient\n\nclient = RustClient()\n\n# Get app information (GIL-free!)\napp = client.get_app(\"com.spotify.music\")\nprint(f\"{app.title}: {app.score}\u2b50 ({app.ratings:,} ratings)\")\n\n# Get reviews\nreviews, next_token = client.get_reviews(\"com.spotify.music\")\nfor review in reviews[:5]:\n    print(f\"{review.user_name}: {review.score}\u2b50\")\n```\n\n### Option 3: AsyncClient (Easy Async)\n\n```python\nimport asyncio\nfrom playfast import AsyncClient\n\n\nasync def main():\n    async with AsyncClient() as client:\n        app = await client.get_app(\"com.spotify.music\")\n        print(f\"{app.title}: {app.score}\u2b50\")\n\n\nasyncio.run(main())\n```\n\n## \ud83d\udcda Examples\n\nSee the [`examples/`](examples/) directory for more:\n\n- [`01_async_client.py`](examples/01_async_client.py) - AsyncClient basics\n- [`02_rust_client.py`](examples/02_rust_client.py) - RustClient for max performance\n- [`03_batch_api.py`](examples/03_batch_api.py) - High-level batch API\n- [`04_countries_and_categories.py`](examples/04_countries_and_categories.py) - Country optimization\n\n## \ud83d\udcd6 Documentation\n\n- **[Getting Started](docs/getting_started.md)** - Installation and first steps\n- **[Quick Start](docs/quick_start.md)** - Practical examples\n- **[API Reference](docs/api/)** - Complete API documentation\n- **[Batch API Guide](docs/BATCH_API.md)** - Batch processing guide\n\n## \ud83c\udfd7\ufe0f Architecture\n\nPlayfast uses **pure Rust** for both HTTP and parsing:\n\n```bash\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502   Python Layer                      \u2502\n\u2502   - Batch API (high-level)          \u2502\n\u2502   - RustClient / AsyncClient        \u2502\n\u2502   - Pydantic Models                 \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n               \u2502 PyO3 Bindings\n               \u25bc\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502   Rust Core                         \u2502\n\u2502   - HTTP Client (reqwest)           \u2502\n\u2502   - HTML Parser (scraper)           \u2502\n\u2502   - Parallel Processing (rayon)     \u2502\n\u2502   - Complete GIL Release            \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n```\n\n### Three Client Options\n\n| Method          | Speed  | Ease   | Best For       |\n| --------------- | ------ | ------ | -------------- |\n| **Batch API**   | \u26a1\u26a1\u26a1 | \u2b50\u2b50\u2b50 | Multiple items |\n| **RustClient**  | \u26a1\u26a1\u26a1 | \u2b50\u2b50   | Single items   |\n| **AsyncClient** | \u26a1\u26a1   | \u2b50\u2b50   | Async code     |\n\n## \ud83c\udf0d Multi-Country Optimization\n\nPlayfast optimizes global data collection:\n\n```python\nfrom playfast import get_unique_countries, get_representative_country\n\n# Instead of 247 countries, use 93 unique stores (2.7x faster!)\nunique = get_unique_countries()  # 93 unique Play Stores\n\n# Get representative for any country\nrep = get_representative_country(\n    \"fi\"\n)  # Finland \u2192 Vanuatu store (shared by 138 countries)\n```\n\n## \ud83d\udd27 Development\n\n```bash\n# Clone repository\ngit clone https://github.com/mixL1nk/playfast.git\ncd playfast\n\n# Install dependencies\nuv sync\n\n# Build Rust extension\nuv run maturin develop --release\n\n# Run tests\nuv run pytest\n\n# Run examples\nuv run python examples/basic.py\n\n# Run benchmarks\nuv run python benchmarks/batch_apps_benchmark.py\n```\n\nSee [Development Setup](docs/development/setup.md) for detailed instructions.\n\n## \ud83e\udd1d Contributing\n\nContributions are welcome! Please:\n\n1. Fork the repository\n1. Create a feature branch\n1. Make your changes\n1. Add tests\n1. Submit a pull request\n\n## \ud83d\udcdd License\n\nMIT License - see [LICENSE](LICENSE) for details.\n\n## \ud83d\ude4f Acknowledgments\n\n- Built with [PyO3](https://github.com/PyO3/pyo3) (Rust-Python bindings)\n- Inspired by [google-play-scraper](https://github.com/facundoolano/google-play-scraper)\n- HTTP: [reqwest](https://github.com/seanmonstar/reqwest)\n- Parsing: [scraper](https://github.com/causal-agent/scraper)\n\n## \u26a0\ufe0f Disclaimer\n\nThis tool is for educational and research purposes only. Please respect Google Play Store's Terms of Service. Use responsibly with appropriate rate limiting.\n\n______________________________________________________________________\n\n**Made with \u2764\ufe0f using Rust + Python**\n\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Playfast - Lightning-Fast Google Play Store Scraper",
    "version": "0.4.0",
    "project_urls": {
        "changelog": "https://github.com/mixL1nk/playfast/blob/master/CHANGELOG.md",
        "documentation": "https://mixl1nk.github.io/playfast/",
        "source": "https://github.com/mixL1nk/playfast"
    },
    "split_keywords": [
        "google-play",
        " scraper",
        " async",
        " rust",
        " pyo3",
        " performance",
        " free-threading"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "311a802b7ed5269c25f703db5a3c93e82baf1a5420ab35f3aeb4a816eeaddf69",
                "md5": "a8fa373c1fb429e2b8c84b926d84b872",
                "sha256": "ad792983fc975f6b464e13537627add6dc526e7f3170d4c5ee6248bd6123f59b"
            },
            "downloads": -1,
            "filename": "playfast-0.4.0-cp311-abi3-macosx_10_12_x86_64.whl",
            "has_sig": false,
            "md5_digest": "a8fa373c1fb429e2b8c84b926d84b872",
            "packagetype": "bdist_wheel",
            "python_version": "cp311",
            "requires_python": ">=3.11",
            "size": 2702489,
            "upload_time": "2025-10-14T12:52:58",
            "upload_time_iso_8601": "2025-10-14T12:52:58.145167Z",
            "url": "https://files.pythonhosted.org/packages/31/1a/802b7ed5269c25f703db5a3c93e82baf1a5420ab35f3aeb4a816eeaddf69/playfast-0.4.0-cp311-abi3-macosx_10_12_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "4175c161f1c450d82bbed36bd77893bcbb2af3154a08217e1d8dd97dd13421aa",
                "md5": "4afe2424f8193dac212a5a79bba394d0",
                "sha256": "1c5d6ffeffc1311aa78ab076594f3fedd324e9f480c70f5b941e686a64911332"
            },
            "downloads": -1,
            "filename": "playfast-0.4.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "has_sig": false,
            "md5_digest": "4afe2424f8193dac212a5a79bba394d0",
            "packagetype": "bdist_wheel",
            "python_version": "cp311",
            "requires_python": ">=3.11",
            "size": 2901103,
            "upload_time": "2025-10-14T12:52:59",
            "upload_time_iso_8601": "2025-10-14T12:52:59.484523Z",
            "url": "https://files.pythonhosted.org/packages/41/75/c161f1c450d82bbed36bd77893bcbb2af3154a08217e1d8dd97dd13421aa/playfast-0.4.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "e69f9be9328a856ad42407fa697524b802821852a72344e5dc6f176c288d56e8",
                "md5": "3a3efa6a620e692832f9a0ecfc9897d0",
                "sha256": "f06f89122832529f267e100604fd972b26f83ad08256f016f211b731dd1c66df"
            },
            "downloads": -1,
            "filename": "playfast-0.4.0-cp311-abi3-win_amd64.whl",
            "has_sig": false,
            "md5_digest": "3a3efa6a620e692832f9a0ecfc9897d0",
            "packagetype": "bdist_wheel",
            "python_version": "cp311",
            "requires_python": ">=3.11",
            "size": 2329163,
            "upload_time": "2025-10-14T12:53:01",
            "upload_time_iso_8601": "2025-10-14T12:53:01.034389Z",
            "url": "https://files.pythonhosted.org/packages/e6/9f/9be9328a856ad42407fa697524b802821852a72344e5dc6f176c288d56e8/playfast-0.4.0-cp311-abi3-win_amd64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "41ef6b2635214f1a4b9160d0c7634307e685a9ea7494345937c1dfcf2ef0bb0e",
                "md5": "6a791276b7ade5bb9ccea2856292a3f3",
                "sha256": "9bde3024e47f180ac7a26154cb3f0df8561bb2a27d22c20cb99993b4791c7e8f"
            },
            "downloads": -1,
            "filename": "playfast-0.4.0.tar.gz",
            "has_sig": false,
            "md5_digest": "6a791276b7ade5bb9ccea2856292a3f3",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.11",
            "size": 278884,
            "upload_time": "2025-10-14T12:53:02",
            "upload_time_iso_8601": "2025-10-14T12:53:02.578350Z",
            "url": "https://files.pythonhosted.org/packages/41/ef/6b2635214f1a4b9160d0c7634307e685a9ea7494345937c1dfcf2ef0bb0e/playfast-0.4.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-10-14 12:53:02",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "mixL1nk",
    "github_project": "playfast",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "playfast"
}
        
Elapsed time: 1.27747s