360 Secure SkillHub
360 安全技能中心

scavio-google-play

该工具通过Scavio API提供Google Play查询服务,含三大核心端点:搜索匹配关键词的Android应用(约30个)、获取含真实安装量、权限树等的完整应用列表、分页获取评论(每个请求消耗2 credits)。适用于应用查找、竞品分析、ASO研究、评分追踪等场景。输入为带API密钥的POST请求,支持多语言/地区参数;输出为结构化JSON,包含数据、信用消耗等信息。

scavio-ai
scavio-ai
热度 21.81
最近更新 2026-08-19 00:42:15
分类:搜索依赖:第三方 API应用场景:市场分析 / 研究

安装技能

复制下面的话术发给你的 Agent,它会通过 secure-skills 检索并安装该技能。

执行命令安装此 skill: npx secure-skills-cli add scavio-google-play
Metadata
name
scavio-google-play
description
Search Google Play, read a full Android app listing including the real install count and Data safety table, and page reviews by cursor. 3 endpoints, 2 credits each, structured JSON.
version
1.0.0
tags
google-play, play-store, android, aso, app-store-optimization, mobile-apps, app-reviews, install-count, data-safety, permissions, app-metadata, competitor-research, agents, langchain, crewai, autogen, structured-data, json, ai-agents
metadata
{"openclaw":{"requires":{"env":["SCAVIO_API_KEY"]},"primaryEnv":"SCAVIO_API_KEY","timeout":90,"throttle":1,"emoji":"📲","homepage":"https://scavio.dev/docs/google-play-search"}}

Google Play via Scavio

Search Google Play, pull a full Android store listing - including the real install count Play publishes but never renders, the whole permission tree and the Data safety table - and page reviews by cursor. All three endpoints return structured JSON.

When to trigger

Use this skill when the user asks to:

  • Find Android apps or games matching a keyword
  • Pull an app's full Play listing: installs, rating histogram, IAPs, permissions, Data safety, changelog
  • Read Google Play reviews for an app, beyond the handful the store page shows
  • Compare an Android app against competitors, or check a developer's identity and legal contact
  • Do Android ASO research across storefronts and languages
  • Track an app's rating distribution or changelog over time

Setup

Get a free API key at scavio.dev (50 free credits to get started, no card required):

export SCAVIO_API_KEY=sk_live_your_key

Every request is a POST with a JSON body and:

Authorization: Bearer $SCAVIO_API_KEY

Endpoints

Base URL: https://api.scavio.dev. All paths are under /api/v1/googleplay. Every endpoint costs 2 credits.

Endpoint Credits What it returns
POST /api/v1/googleplay/search 2 One shelf of ranked apps (~30). No pagination.
POST /api/v1/googleplay/app 2 The complete store listing, plus the 20 server-rendered reviews
POST /api/v1/googleplay/reviews 2 A page of reviews, cursor-paginated

Google Play is a premium domain upstream, which is why it is 2 credits and not 1. Budget accordingly before planning a deep review crawl.

Workflow

  1. Find an app: call /googleplay/search with query. You get one shelf of roughly 30 apps. A branded query also returns Play's hero card as result 1, projected to the same row shape, plus Play's related-query rail.
  2. Read the listing: call /googleplay/app with app_id - a package name (com.notion.id) or any play.google.com URL carrying one in its id param.
  3. The listing already carries 20 reviews. Play server-renders them and they ride along at no extra cost. Only call /googleplay/reviews when you need to page past those 20 or sort differently.
  4. Page reviews: call /googleplay/reviews with app_id, then send next_cursor back as cursor.

Pagination

Search does not paginate. It is one shelf of about 30 apps. There is no page or cursor parameter - do not invent one. Narrow the query instead.

/app does not paginate.

Reviews paginate by cursor, and the cursor is strict. It is opaque, single-use, and it encodes the sort as well as the position. Send it back with the same sort it came from. A cursor past the last review is a 404, not an empty page - that is the stop signal.

Parameters

Search (/search)

Parameter Type Default Description
query string required Search term (1-200 chars)
hl string en Interface language (2-20 chars). Changes the storefront, not only the strings.
gl string us Country (2-10 chars)

App (/app)

Parameter Type Default Description
app_id string required Package name, or any play.google.com URL carrying one in its id param (1-500 chars)
hl string en Interface language
gl string us Country

Reviews (/reviews)

Parameter Type Default Description
app_id string required Package name or Play URL (1-500 chars)
sort string newest relevance, newest, rating
count integer 50 Reviews per page, 1-200. Capped at 200 on our side.
cursor string -- The previous response's next_cursor. Opaque, single-use, sort-encoded.
hl string en Interface language
gl string us Country

hl moves more than the words

At hl=pt-BR the title, the description, the install formatting and the content rating all change with it - it selects a storefront, not a translation layer. Play also silently falls back to English/US on any value it does not serve, so an unexpected language in the response means the value was not supported, not that the call failed.

Examples

import requests

BASE = "https://api.scavio.dev"
# Your key from https://scavio.dev. Load it from your environment or secret
# store in real code - keep it out of source control.
API_KEY = "sk_your_key_here"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}

# 1. Search - one shelf of ~30 apps, no pagination
apps = requests.post(f"{BASE}/api/v1/googleplay/search", headers=HEADERS,
    json={"query": "habit tracker", "hl": "en", "gl": "us"}).json()

# 2. Full listing - package name or any play.google.com URL
app = requests.post(f"{BASE}/api/v1/googleplay/app", headers=HEADERS,
    json={"app_id": "com.spotify.music"}).json()

# The 20 server-rendered reviews are already in there - do not pay again for them.

# 3. Page past them, sorted by rating
reviews = requests.post(f"{BASE}/api/v1/googleplay/reviews", headers=HEADERS,
    json={"app_id": "com.spotify.music", "sort": "rating", "count": 200}).json()

Cursor paging, capped so it cannot run away with the user's credits. The cursor encodes the sort, so the sort must not change between pages, and running past the end is a 404:

def paged_reviews(app_id, sort="newest", count=200, max_pages=5):
    """2 credits per page. 5 pages = 10 credits."""
    cursor, pages = None, []
    for _ in range(max_pages):
        body = {"app_id": app_id, "sort": sort, "count": count}
        if cursor:
            body["cursor"] = cursor    # same sort every time: the cursor encodes it
        r = requests.post(f"{BASE}/api/v1/googleplay/reviews", headers=HEADERS, json=body)
        if r.status_code == 404:
            break                      # cursor ran past the last review: this is the end
        data = r.json()["data"]
        pages.append(data)
        cursor = data.get("next_cursor")
        if not cursor:
            break
    return pages

Response shapes

Every response uses the envelope { data, response_time, credits_used, credits_remaining }.

  • search - ranked apps: package name, title, developer, rating, install count, price and IAP range, content rating, icon, screenshots. A branded query puts the hero card first in the same row shape, and Play's related-query rail comes along.
  • app - installs (including the real count Play publishes but never renders on the page), rating and star histogram, description, developer identity and legal contact, price and IAPs, categories and gameplay tags, screenshots and trailer, version and Android requirement, release and update dates, changelog, the full permission tree, the Data safety table, the 20 server-rendered reviews, and the similar-apps and more-by-developer rails.
  • reviews - star score, full text, author, thumbs-up count, developer reply, and the app version the reviewer was running. Paged via next_cursor.

Guardrails

  • Every call is 2 credits, not 1. Say so before planning a multi-page crawl: a 10-page review pull is 20 credits.
  • /app already contains 20 reviews. Do not call /reviews for the same app unless you need to go deeper or change the sort - that is a second premium call for data you already have.
  • Search is one shelf of ~30 apps with no pagination. Never tell the user there is a page 2; narrow the query instead.
  • Keep sort fixed while paging reviews. The cursor carries the sort, and changing it mid-walk invalidates the sequence.
  • Do not treat a 404 mid-walk as a failure - a cursor past the last review is how the feed ends.
  • Games are folded into the apps vertical and are covered. Books and films are not - they use a different card shape entirely.
  • Never fabricate package names, install counts, ratings, permissions or review text. Only return API data.

Failure handling

  • 400 means an invalid or missing parameter - fix and retry.
  • 401 means the API key is invalid or missing. Check SCAVIO_API_KEY.
  • 404 on /reviews while paging means the cursor ran past the last review. Stop; this is normal.
  • A reviews call that answers 200 with an empty payload is a billed 404 - premium price paid to learn the package has no reviews or does not exist. Confirm the package with /app before crawling reviews for it.
  • 429 means rate or usage limit exceeded. Wait before retrying. See https://scavio.dev/docs/rate-limits.
  • 502 / 503 mean upstream is temporarily unavailable - wait a few seconds and retry.
  • If SCAVIO_API_KEY is not set, prompt the user to export it before continuing.

Python SDK

langchain-scavio has no Google Play tool - use the Scavio SDK directly:

pip install scavio==0.15.0
from scavio import ScavioClient

client = ScavioClient()  # reads SCAVIO_API_KEY

apps = client.google_play.search("habit tracker", gl="us")
app = client.google_play.app("com.spotify.music")
page1 = client.google_play.reviews("com.spotify.music", sort="rating", count=200)
page2 = client.google_play.reviews("com.spotify.music", sort="rating", count=200,
                                   cursor=page1["data"]["next_cursor"])

JavaScript / TypeScript:

npm install scavio@0.15.0
import { Scavio } from "scavio";

const scavio = new Scavio(); // reads SCAVIO_API_KEY
const app = await scavio.googlePlay.app({ app_id: "com.spotify.music" });