{
  "openapi": "3.0.1",
  "info": {
    "title": "Google Play Reviews Scraper — Android App Reviews & Ratings",
    "description": "Play Store reviews by language and country for Android apps by package name or URL. One row per review: 1-5 rating, text, reviewer, thumbs-up, app version, developer reply. Free app row: Google Play ratings. Filters before billing: star rating (negative, one-star reviews), since date (new reviews).",
    "version": "1.0",
    "x-build-id": "udbqSwnHhjJXb0p6N"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/kestrel~google-play-reviews-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-kestrel-google-play-reviews-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/acts/kestrel~google-play-reviews-scraper/runs": {
      "post": {
        "operationId": "runs-sync-kestrel-google-play-reviews-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor and returns information about the initiated run in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/runsResponseSchema"
                }
              }
            }
          }
        }
      }
    },
    "/acts/kestrel~google-play-reviews-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-kestrel-google-play-reviews-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "inputSchema": {
        "type": "object",
        "properties": {
          "appIds": {
            "title": "Package names",
            "uniqueItems": true,
            "type": "array",
            "description": "Android package names, e.g. [\"com.whatsapp\", \"com.spotify.music\"] — the id= part of any Google Play URL, and what an earlier run's app_id gives you. Use for \"reviews of com.whatsapp\". App names are not accepted (Play has no open search API): open the app's Play page and copy the id. A package that is not on Play in a country costs nothing: its status row says not_found. Each package is read for every language × country pair.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "appUrls": {
            "title": "Google Play URLs",
            "uniqueItems": true,
            "type": "array",
            "description": "Google Play app pages, e.g. [\"https://play.google.com/store/apps/details?id=com.whatsapp\"]. Only the package name is read from the URL; its hl and gl are NOT used — languages and countries decide which locales are read. A URL from another site ends the run before anything is charged. A URL and its package name are the same app and are read once.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "languages": {
            "title": "Languages",
            "uniqueItems": true,
            "type": "array",
            "description": "Play language codes (hl), e.g. [\"en\", \"de\", \"pt-BR\", \"ja\", \"zh-TW\"]; default [\"en\"]. Use [\"zh-TW\"] with countries=[\"tw\"] for the tested Taiwan example. Each app is read for every language × country pair; rows carry the request language. Reviews retain source text (no actor translation). A review listed under two languages is delivered and billed once. Cost scales with apps × languages × countries × maxReviewsPerApp.",
            "default": [
              "en"
            ],
            "items": {
              "type": "string"
            }
          },
          "countries": {
            "title": "Countries",
            "uniqueItems": true,
            "type": "array",
            "description": "Play country codes (gl), e.g. [\"us\", \"gb\", \"in\", \"br\"]; default [\"us\"]. Any two-letter code; every row carries country. Google decides what it shows under each language × country pair, so the same review can appear under several (delivered and billed once; the status row counts duplicates). Name the markets the app has users in; one language and one country is the cheapest run.",
            "default": [
              "us"
            ],
            "items": {
              "type": "string"
            }
          },
          "maxReviewsPerApp": {
            "title": "Max reviews per app, language and country",
            "minimum": 0,
            "maximum": 100000,
            "type": "integer",
            "description": "Reviews to read per app, language AND country, e.g. 200; default 100; 0 = every review Google pages out (hundreds of thousands for big apps: cap the run with maxTotalChargeUsd). The main cost control: at most N × $0.004 per pair. The filters apply to these N reads, so 300 with maxRating 2 delivers the 1-2 star reviews among the 300 read — except when minRating = maxRating: that star value is filtered by Google itself and N reviews of that star are delivered. Google answers up to 100 per request.",
            "default": 100
          },
          "sort": {
            "title": "Order",
            "enum": [
              "most_recent",
              "most_relevant",
              "rating"
            ],
            "type": "string",
            "description": "\"most_recent\" (default; schedule this), \"most_relevant\" (Google Play's own order), \"rating\" (5-star first). Applied by Google before maxReviewsPerApp: \"most_recent\" with 100 reads the 100 newest reviews of each language × country pair. There is no lowest-rating-first order: for complaints use maxRating, or minRating = maxRating = 1.",
            "default": "most_recent"
          },
          "minRating": {
            "title": "Only reviews rated at least",
            "minimum": 0,
            "maximum": 5,
            "type": "integer",
            "description": "0 (default) = no lower bound. 1-5 = keep only reviews with at least this many stars, e.g. 4 for praise only. Set minRating and maxRating to the SAME value (both 1 for one-star reviews) and Google filters server-side: the other reviews are never fetched and the N read are all that star. Otherwise applied after the read and before billing; filtered reviews are never charged (the status row counts them in filtered).",
            "default": 0
          },
          "maxRating": {
            "title": "Only reviews rated at most",
            "minimum": 0,
            "maximum": 5,
            "type": "integer",
            "description": "0 (default) = no upper bound. 1-5 = keep only reviews with at most this many stars, e.g. 2 for a complaints feed that pays nothing for the happy ones. Applied before billing; must be at least minRating. Use for \"negative reviews\", \"complaints\"; for exactly one star value set minRating = maxRating (filtered by Google, nothing is fetched to be discarded).",
            "default": 0
          },
          "sinceDate": {
            "title": "Only reviews on or after",
            "type": "string",
            "description": "Empty (default) = all dates. Keep only reviews on or after this day: \"2026-09-01\", or relative to the run day so a schedule never goes stale: \"7 days\", \"2 weeks\", \"3 months\", \"yesterday\". For a daily new-reviews feed pass \"1 day\" with sort \"most_recent\". Applied before billing; older reviews that were read are not charged. There is no end date and no \"since last run\" memory: dedupe on review_id downstream.",
            "default": ""
          },
          "requireText": {
            "title": "Only reviews with written text",
            "type": "boolean",
            "description": "false (default) = keep every review. true = drop reviews that are a star rating with no words before billing, so you pay only for reviews that say something. Use for \"reviews with text\", sentiment analysis, complaint triage.",
            "default": false
          },
          "includeAppRow": {
            "title": "Include an app row",
            "type": "boolean",
            "description": "true (default) = one free app row per app, language and country: app_name, developer, category, content_rating, rating_avg, rating_count, price, currency, icon, description. Never charged. Use for \"Google Play rating of app X\" or a daily rating history; false = review rows only.",
            "default": true
          },
          "sessions": {
            "title": "Parallel sessions",
            "minimum": 1,
            "maximum": 16,
            "type": "integer",
            "description": "Parallel proxy sessions (egress IPs), 1-16; default 4. Google allows about one request a second per IP and answers up to 100 reviews per request, so 4 sessions read a few hundred reviews a second. Raise it for large runs; it changes speed, not cost.",
            "default": 4
          },
          "perIp": {
            "title": "Requests per second per IP",
            "minimum": 0.1,
            "maximum": 3,
            "type": "number",
            "description": "Requests per second per session, 0.1-3; default 1. Google refuses bursts above about 1 per second per IP and the fetcher then rotates and backs off, so a higher value earns retries, not speed.",
            "default": 1
          },
          "proxyConfiguration": {
            "title": "Proxy",
            "type": "object",
            "description": "Default: Apify Proxy, datacentre group. Google Play's review call needs no login, but each IP is throttled at about one request a second, so a run of more than a few thousand reviews needs several IPs. Small runs work without a proxy.",
            "default": {
              "useApifyProxy": true
            }
          }
        }
      },
      "runsResponseSchema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "actId": {
                "type": "string"
              },
              "userId": {
                "type": "string"
              },
              "startedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "finishedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "status": {
                "type": "string",
                "example": "READY"
              },
              "meta": {
                "type": "object",
                "properties": {
                  "origin": {
                    "type": "string",
                    "example": "API"
                  },
                  "userAgent": {
                    "type": "string"
                  }
                }
              },
              "stats": {
                "type": "object",
                "properties": {
                  "inputBodyLen": {
                    "type": "integer",
                    "example": 2000
                  },
                  "rebootCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "restartCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "resurrectCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "computeUnits": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "options": {
                "type": "object",
                "properties": {
                  "build": {
                    "type": "string",
                    "example": "latest"
                  },
                  "timeoutSecs": {
                    "type": "integer",
                    "example": 300
                  },
                  "memoryMbytes": {
                    "type": "integer",
                    "example": 1024
                  },
                  "diskMbytes": {
                    "type": "integer",
                    "example": 2048
                  }
                }
              },
              "buildId": {
                "type": "string"
              },
              "defaultKeyValueStoreId": {
                "type": "string"
              },
              "defaultDatasetId": {
                "type": "string"
              },
              "defaultRequestQueueId": {
                "type": "string"
              },
              "buildNumber": {
                "type": "string",
                "example": "1.0.0"
              },
              "containerUrl": {
                "type": "string"
              },
              "usage": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "integer",
                    "example": 1
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "usageTotalUsd": {
                "type": "number",
                "example": 0.00005
              },
              "usageUsd": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "number",
                    "example": 0.00005
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}