# ASO Listing Checker: Google Play and App Store limits (`netaudit-labs/aso-listing-checker`) Actor

Bulk-check Google Play and App Store listings in every language before upload: character limits per field, wasted characters in the App Store keyword field, name/subtitle overlap, promo terms and emojis in titles, keyword density. Reads live App Store listings by ID.

- **URL**: https://apify.com/netaudit-labs/aso-listing-checker.md
- **Developed by:** [NetAudit Labs](https://apify.com/netaudit-labs) (community)
- **Categories:** Developer tools, SEO tools
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$3.00 / 1,000 listing checkeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### What does ASO Listing Checker do?

It checks your Google Play and App Store listings, in every language, before you upload them, and returns one row per listing:

- **Character limits per field**: Google Play title 30, short description 80, full description 4,000; App Store name 30, subtitle 30, keywords 100, promotional text 170, description 4,000, What's New 4,000. Each field gets its length, its limit, the characters left and its UTF-8 byte size.
- **App Store keyword field audit**: spaces after commas, words already indexed from the name or subtitle, repeated words, stop words, and the total number of **characters you can win back** for new keywords.
- **Name and subtitle overlap** on the App Store (each word is indexed once).
- **Policy warnings**: promotional terms in a Google Play title or short description ("best", "#1", "free", "top"...), emojis in the app name, titles in capitals only.
- **Keyword density** of the full description (top 10 terms), with a warning above 3 % on Google Play.
- **Live App Store reading**: give App Store IDs or bundle IDs and countries, and the public name, description and release notes are read from each storefront and checked.

### Who is it for?

Indie developers, ASO consultants and localization agencies who ship listings in 10 to 40 languages and want to catch the field that is 3 characters too long before the console rejects it, or the keyword field that wastes 15 characters on repeats.

### How much does it cost?

Pay per event: **one event per listing checked** (one store, one language). Rows with an error (app not found in a storefront) are not charged. Use **Max listings** as a spending cap.

### Input example

```json
{
  "listings": [
    { "store": "play", "locale": "de-DE", "title": "Gewohnheiten Tracker: Tägliche Ziele", "shortDescription": "Baue Gewohnheiten auf, die bleiben." },
    { "store": "appstore", "locale": "en-US", "name": "Habit Tracker: Daily Goals", "subtitle": "Streaks and reminders", "keywords": "habit, routine, goals, tracker, streak" }
  ],
  "appStoreApps": ["1438388363"],
  "countries": ["us", "de"]
}
```

### Notes

- Counting is per Unicode character, as the consoles count. Byte size is returned as well for languages with multi-byte scripts.
- The App Store subtitle, keyword field and promotional text are not public: paste them in **Listings** to check them. Live reading covers the public fields only.
- Google Play listings are checked from what you paste; the Actor does not log in to any console.
- Issues and feature requests in the Issues tab are answered quickly.

# Actor input Schema

## `listings` (type: `array`):

One object per store listing and language. Google Play: store "play", locale, title, shortDescription, fullDescription. App Store: store "appstore", locale, name, subtitle, keywords, promotionalText, description, whatsNew. Missing fields are skipped.

## `appStoreApps` (type: `array`):

Optional: App Store IDs or bundle IDs. The public name, description and release notes are read in each country and checked.

## `countries` (type: `array`):

Two-letter storefront codes (us, gb, de, fr, jp...). Used with App Store apps only.

## `maxListings` (type: `integer`):

Hard cap on listings checked (and charged).

## Actor input object example

```json
{
  "listings": [
    {
      "store": "play",
      "locale": "en-US",
      "title": "Habit Tracker: Daily Goals",
      "shortDescription": "Build habits that stick with streaks, reminders and simple stats.",
      "fullDescription": "Track habits every day.\nSet reminders and see your streaks."
    },
    {
      "store": "appstore",
      "locale": "en-US",
      "name": "Habit Tracker: Daily Goals",
      "subtitle": "Streaks, reminders, stats",
      "keywords": "habit, routine, goals, streak, planner, tracker"
    }
  ],
  "countries": [
    "us"
  ],
  "maxListings": 10000
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

## `allFields` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "listings": [
        {
            "store": "play",
            "locale": "en-US",
            "title": "Habit Tracker: Daily Goals",
            "shortDescription": "Build habits that stick with streaks, reminders and simple stats.",
            "fullDescription": "Track habits every day.\nSet reminders and see your streaks."
        },
        {
            "store": "appstore",
            "locale": "en-US",
            "name": "Habit Tracker: Daily Goals",
            "subtitle": "Streaks, reminders, stats",
            "keywords": "habit, routine, goals, streak, planner, tracker"
        }
    ],
    "countries": [
        "us"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("netaudit-labs/aso-listing-checker").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "listings": [
        {
            "store": "play",
            "locale": "en-US",
            "title": "Habit Tracker: Daily Goals",
            "shortDescription": "Build habits that stick with streaks, reminders and simple stats.",
            "fullDescription": """Track habits every day.
Set reminders and see your streaks.""",
        },
        {
            "store": "appstore",
            "locale": "en-US",
            "name": "Habit Tracker: Daily Goals",
            "subtitle": "Streaks, reminders, stats",
            "keywords": "habit, routine, goals, streak, planner, tracker",
        },
    ],
    "countries": ["us"],
}

# Run the Actor and wait for it to finish
run = client.actor("netaudit-labs/aso-listing-checker").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "listings": [
    {
      "store": "play",
      "locale": "en-US",
      "title": "Habit Tracker: Daily Goals",
      "shortDescription": "Build habits that stick with streaks, reminders and simple stats.",
      "fullDescription": "Track habits every day.\\nSet reminders and see your streaks."
    },
    {
      "store": "appstore",
      "locale": "en-US",
      "name": "Habit Tracker: Daily Goals",
      "subtitle": "Streaks, reminders, stats",
      "keywords": "habit, routine, goals, streak, planner, tracker"
    }
  ],
  "countries": [
    "us"
  ]
}' |
apify call netaudit-labs/aso-listing-checker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,netaudit-labs/aso-listing-checker"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/e3nC7EJHGbYTBo3ne/builds/2wOwVfQmaVugTqIpO/openapi.json
