# Competitor Review Teardown — Instant Battle-Card (`bikram07/competitor-teardown`) Actor

Turn rivals' App Store reviews into a ranked battle-card: top complaints (with quotes + %), top praises, most-requested features, switch-trigger quotes, sentiment trend, and ad angles. The analysis, not a 500-row data dump. Deterministic, no LLM, no API keys.

- **URL**: https://apify.com/bikram07/competitor-teardown.md
- **Developed by:** [Bikram](https://apify.com/bikram07) (community)
- **Categories:** Marketing, E-commerce, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Competitor Review Teardown — Instant Battle-Card

**Stop reading 500 reviews by hand. Drop in your competitors → get a ranked battle-card you can act on today.**

This Actor pulls a competitor's public reviews and runs a deterministic analysis engine over them — no LLM, no API keys, no per-run AI cost — and returns a **battle-card**, not a data dump:

- 🔴 **Top complaints**, ranked by frequency, each with the **% of unhappy reviewers** who mention it and **verbatim quotes**
- 🟢 **Top praises** (what you'll be measured against)
- 💡 **Most-requested features** (the roadmap gaps your competitor is ignoring)
- 🚪 **Switch-trigger quotes** — the exact words people use when they cancel or leave
- 📈 **Sentiment over time** (is the competitor getting better or worse?)
- 🎯 **Ready-to-use ad angles** templated from the top complaints

### How it works

1. Paste one or more competitors (App Store app URLs or IDs).
2. The Actor fetches up to ~500 recent reviews per competitor from the public Apple App Store RSS feed.
3. A deterministic NLP engine clusters reviews into product themes (pricing, bugs, support, UX, performance, features, …), splits complaints vs praise by star rating, ranks them, and pulls representative quotes.
4. You get one clean battle-card record per competitor (plus a cross-competitor comparison when you give it 2+).

### What you get (output)

One dataset record per competitor:

```jsonc
{
  "competitor": "Duolingo",
  "reviewsAnalyzed": 300,
  "avgRating": 3.88,
  "ratingDistribution": { "1": 31, "2": 18, "3": 22, "4": 40, "5": 189 },
  "topComplaints": [
    { "theme": "Pricing & billing", "mentions": 18, "pctOfReviews": 64.3,
      "sampleQuotes": ["Way too expensive for what it does.", "Charged me twice…"] }
  ],
  "topPraises": [ { "theme": "Ease of use / UI", "mentions": 41, "sampleQuotes": ["…"] } ],
  "mostRequestedFeatures": [ { "request": "wish there was an option for Mexican Spanish", "count": 3 } ],
  "switchTriggers": [ { "quote": "cancelled my subscription after…", "count": 5 } ],
  "sentimentTrend": [ { "month": "2026-05", "avgRating": 3.7, "reviews": 88 } ],
  "adAngles": ["Tired of Duolingo's pricing problems? 64% of their unhappy reviewers complain about it — here's the switch."]
}
````

### Input

| Field | What it does |
|---|---|
| **Competitors** | One per line — App Store app URLs (`https://apps.apple.com/us/app/.../id570060128`) or just the numeric ID. Leave empty for a 2-app demo. |
| **App Store country** | Two-letter storefront for the review locale (default `us`). |
| **Max reviews per competitor** | Up to ~500 (default 300). |

### Pricing

Pay-per-event: a small flat **actor-start** fee, then **one charge per competitor battle-card** produced. You pay for the finished analysis, not per review — and a competitor with no findable reviews is never charged.

### Who it's for

- **Product marketers** building battle-cards and switch campaigns
- **Founders / PMs** mining a rival's reviews for roadmap gaps
- **Growth / paid-ads** teams who need ad angles grounded in real customer language
- **App developers** sizing up the competition before a launch

### What it is **not**

- It is **not** a raw review scraper — it returns the *analysis*, not 500 rows to read yourself.
- It does **not** use an LLM, so output is deterministic and reproducible (and free of hallucinated "insights").
- v1 covers the **Apple App Store**. Google Play and Trustpilot (which sits behind Cloudflare and needs a residential proxy) are on the roadmap.

### Notes

- 100% public data via the official Apple iTunes RSS feed — no login, no key.
- Built and maintained by [apify.com/bikram07](https://apify.com/bikram07).

# Actor input Schema

## `competitors` (type: `array`):

One competitor per line. Paste App Store app URLs or numeric IDs — e.g. <b>https://apps.apple.com/us/app/duolingo/id570060128</b> or just <b>570060128</b>. Trustpilot domains (e.g. <b>notion.so</b>) are best-effort and may be blocked without a residential proxy. Leave empty to run a 2-app demo.

## `country` (type: `string`):

Two-letter App Store storefront that sets the review locale. Default <b>us</b>.

## `maxReviewsPerCompetitor` (type: `integer`):

How many recent reviews to analyze per competitor. The App Store RSS serves up to ~500. Default 300.

## Actor input object example

```json
{
  "competitors": [
    "https://apps.apple.com/us/app/duolingo/id570060128",
    "https://apps.apple.com/us/app/babbel/id829587759"
  ],
  "country": "us",
  "maxReviewsPerCompetitor": 300
}
```

# 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 = {
    "competitors": [
        "https://apps.apple.com/us/app/duolingo/id570060128",
        "https://apps.apple.com/us/app/babbel/id829587759"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("bikram07/competitor-teardown").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 = { "competitors": [
        "https://apps.apple.com/us/app/duolingo/id570060128",
        "https://apps.apple.com/us/app/babbel/id829587759",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("bikram07/competitor-teardown").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "competitors": [
    "https://apps.apple.com/us/app/duolingo/id570060128",
    "https://apps.apple.com/us/app/babbel/id829587759"
  ]
}' |
apify call bikram07/competitor-teardown --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=bikram07/competitor-teardown",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Competitor Review Teardown — Instant Battle-Card",
        "description": "Turn rivals' App Store reviews into a ranked battle-card: top complaints (with quotes + %), top praises, most-requested features, switch-trigger quotes, sentiment trend, and ad angles. The analysis, not a 500-row data dump. Deterministic, no LLM, no API keys.",
        "version": "0.1",
        "x-build-id": "OQQKkBKfTIkAFIKTm"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/bikram07~competitor-teardown/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-bikram07-competitor-teardown",
                "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/bikram07~competitor-teardown/runs": {
            "post": {
                "operationId": "runs-sync-bikram07-competitor-teardown",
                "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/bikram07~competitor-teardown/run-sync": {
            "post": {
                "operationId": "run-sync-bikram07-competitor-teardown",
                "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": {
                    "competitors": {
                        "title": "Competitors",
                        "type": "array",
                        "description": "One competitor per line. Paste App Store app URLs or numeric IDs — e.g. <b>https://apps.apple.com/us/app/duolingo/id570060128</b> or just <b>570060128</b>. Trustpilot domains (e.g. <b>notion.so</b>) are best-effort and may be blocked without a residential proxy. Leave empty to run a 2-app demo.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "country": {
                        "title": "App Store country",
                        "type": "string",
                        "description": "Two-letter App Store storefront that sets the review locale. Default <b>us</b>.",
                        "default": "us"
                    },
                    "maxReviewsPerCompetitor": {
                        "title": "Max reviews per competitor",
                        "minimum": 20,
                        "maximum": 500,
                        "type": "integer",
                        "description": "How many recent reviews to analyze per competitor. The App Store RSS serves up to ~500. Default 300.",
                        "default": 300
                    }
                }
            },
            "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
                                    }
                                }
                            },
                            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
