# Okendo Review Scraper for Shopify stores (`stanvanrooy6/okendo-scraper`) Actor

Scrape Okendo reviews from any Shopify store: rating, title, text, photos, custom attributes, author, date and product. Store-wide or per product. No login, no API key. JSON, CSV or Excel.

- **URL**: https://apify.com/stanvanrooy6/okendo-scraper.md
- **Developed by:** [Stan Van Rooy](https://apify.com/stanvanrooy6) (community)
- **Categories:** E-commerce, Automation
- **Features:** Limited permissions
- **Stats:** 11 total users, 6 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.64 / 1,000 reviews

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## Okendo Reviews Scraper for Shopify stores 🌟

**Free-plan sample:** Apify Free accounts can collect up to **100 result rows total per run**, shared across all inputs. Upgrade your [Apify plan](https://console.apify.com/billing/subscription) for larger runs. Normal Actor charges apply. The sample resets each run; it is not a daily or monthly quota.

Extract customer reviews from any Shopify store using Okendo. Perfect for competitor analysis, product research, or monitoring your own reviews.

### 🚀 Quick Start

Just provide a store URL and hit run. The scraper automatically detects whether you want:

- **All reviews** from the store (site-wide mode)
- **Reviews for a specific product** (product-specific mode)

That's it! No configuration needed.

### 📥 Input

| Field | Type | Description |
|---|---|---|
| `startUrls` | array | List of store URLs (`store.com`, `https://store.com`) or product URLs (`https://store.com/products/item`) to scrape in batch. |
| `startUrl` | string | Single store or product URL (legacy convenience; merged into `startUrls`). |
| `minRating`, `maxRating` | integer | Filter by star rating (1 to 5). Set `minRating: 1, maxRating: 2` for negative reviews. |
| `verifiedOnly` | boolean | Keep only verified buyer reviews. Default `false`. |
| `mediaOnly` | boolean | Keep only reviews with customer photos or videos. Default `false`. |
| `reviewText` | string | Keyword search within review title and body text. |
| `reviewDateFrom`, `reviewDateTo` | string | Inclusive date window (`YYYY-MM-DD` in UTC). |
| `maxReviews` | integer | Maximum reviews to deliver per URL. Default `100`, `0` means unlimited. |
| `maxScannedReviews` | integer | Maximum source reviews inspected across all URLs in the run when filters are active. Default 10,000. The scan budget can stop collection before maxReviews is reached. |

```json
{
  "startUrls": [{ "url": "https://speargun.com" }],
  "minRating": 4,
  "maxRating": 5,
  "mediaOnly": true,
  "maxReviews": 200
}
```

### 📤 Output

Each review contains detailed fields directly from the Okendo API:

```json
{
  "reviewId": "5f8d9a7b-1c2d-4e3f-a4b5-6c7d8e9f0a1b",
  "subscriberId": "3a1b2c3d-4e5f-4a7b-8c9d-0e1f2a3b4c5d",
  "productId": "shopify-1234567890123",
  "rating": 5,
  "title": "Absolutely love it!",
  "body": "The quality is amazing and it fits perfectly. Highly recommend!",
  "dateCreated": "2023-10-15T14:30:00.000Z",
  "date_utc": "2023-10-15T14:30:00.000Z",
  "reviewer": {
    "displayName": "Sarah J.",
    "isVerified": true
  },
  "verified_buyer": true,
  "productName": "Summer Floral Dress",
  "productImageUrl": "https://cdn.shopify.com/s/files/1/0123/4567/products/dress.jpg",
  "productVariantName": "Blue / M",
  "helpfulCount": 2,
  "images": [
    "https://media-dynamic.okendo.io/images/.../photo.jpg"
  ],
  "videos": [],
  "attributes": [
    {
      "label": "Fit",
      "value": 1
    },
    {
      "label": "Size Purchased",
      "value": "M"
    }
  ],
  "reply": {
    "body": "Thanks for the kind words, Sarah!",
    "dateCreated": "2023-10-16T09:00:00.000Z"
  }
}
```

#### Field Descriptions

- `reviewId` - Unique Okendo review identifier (also in `review_id`)
- `rating` - Star rating (1-5)
- `title` - Review title/headline (also in `review_title` and `reviewTitle`)
- `body` - Full review text
- `dateCreated` - Timestamp when the review was posted
- `reviewer` - Object containing reviewer details (name, verified status)
- `verified_buyer` - Whether the reviewer is a verified buyer
- `productName` - Name of the reviewed product
- `images` / `videos` - Links to customer uploaded photos and videos
- `attributes` - Rated and answered product attributes (e.g., Fit, Comfort, Size Purchased)
- `reply` - The store's public reply, when there is one

### ✨ Features

- **Batch Processing & URL Lists** - Scrape multiple stores or product URLs in a single run with `startUrls`
- **Precision Review Filters** - Filter by star rating (`minRating`/`maxRating`), verified purchases, media attachments, date ranges, or text keywords
- **Smart Mode Detection** - Automatically detects if you want site-wide or product-specific reviews
- **Complete Data** - Gets everything: ratings, verified status, images, product info, and custom attributes
- **Clear results** - A store without Okendo or a product without reviews still ends successfully, and the status message says why
- **Fast** - Uses Okendo APIs directly, no browser overhead
- **Pagination** - Automatically handles multi-page results

### 💡 Use Cases

- **Competitor Research** - See what customers say about competing products
- **Product Insights** - Understand customer sentiment before entering a market
- **Review Monitoring** - Track reviews for your own products
- **Data Analysis** - Export for sentiment analysis or ML training
- **Market Research** - Analyze trends across multiple stores

### ⚠️  Important Notes

- Only works for stores using **Okendo** as their review platform
- If a store doesn't use Okendo, or a product has no reviews yet, the run still succeeds with 0 results and its status message says why (and which scraper fits the store's review app)
- A product URL that no longer opens ends with a clear error instead of returning the whole store's reviews
- Product ID is automatically extracted from Shopify pages
- Each review is returned once, even on stores with 150,000+ reviews (a store that size takes about 70 minutes, so raise the run timeout above the 1 hour default for a full export)

### Monitor a store for new reviews

Only one run can update the same URL and monitoring list at a time. Let it finish before starting another. After an interrupted run, the list may stay busy until that run's timeout expires. Newest-first feeds stop after a stretch of known reviews, so edits deeper in old history may not be detected.

Turn on **Only new reviews (monitoring)** (`onlyNewReviews: true`) and schedule the run. The scraper remembers the reviews it has seen for each store or product URL, so every scheduled run returns only reviews that are new or were edited since the last run. You pay for those rows and the usual start fee; a run that finds nothing new saves no rows.

- **First run (baseline):** works like a normal run and saves up to `maxReviews` reviews per URL (`0` saves the full history once). It then reads the rest of the store without saving it, so every existing review counts as known. On a large store this first run takes longer.
- **Later runs:** return new reviews and reviews whose rating, title, text or store reply changed. Each row carries `monitor_status`: `new` or `changed`. Unchanged reviews are skipped and not charged.
- The memory is kept per URL in a key-value store named `okendo-reviews-monitor` in your Apify account. Use `monitorName` to keep separate lists for the same stores, for example one per client.
- Filters still apply. Reviews outside your filters are not remembered, so widening the filters later can return older reviews that now match.
- Deleted reviews are not reported, and a review missing from a shortened run is never treated as deleted.
- Let a run finish before the next one starts on the same stores, otherwise both runs can return the same new review.

Schedule example:

1. Save this input as a task:

```json
{
  "startUrls": [
    { "url": "https://speargun.com" }
  ],
  "onlyNewReviews": true,
  "maxReviews": 100
}
```

2. In Apify Console open **Schedules**, create a schedule (for example every day at 08:00, cron `0 8 * * *`) and add the task.
3. Connect an integration (Slack, email, Zapier, Make or a webhook) to the task to receive each run's new reviews.

### Pricing

Pay per result: **$0.80 per 1,000 reviews** plus a small Actor start fee ($0.0025 per GB of memory, one event per run). A 5,000-review export costs about $4. Volume users on higher Apify plans pay less per review.

### 📞 Feedback & Feature Requests

I actively maintain this actor. Found a bug or need a field? Open an issue on the Issues tab with the store URL.

### 🎯 Example Usage

**Scrape all reviews from a store:**

```json
{
  "startUrl": "https://speargun.com",
  "maxReviews": 100
}
```

**Scrape reviews for a specific product:**

```json
{
  "startUrl": "https://speargun.com/products/mahogany-competition-series-riffe-spearfishing-speargun",
  "maxReviews": 50
}
```

### ❓ FAQ

#### Does this work with any Shopify store?

Yes, as long as the store uses Okendo for their reviews! If a store uses a different app (like Loox or Yotpo), this scraper won't find any data.

#### Why did I get 0 results?

This usually means either the store doesn't use Okendo, or the specific product URL you provided has no reviews yet. The run's status message tells you which, and names the right scraper when the store uses another review app.

#### Can I scrape more than 100 reviews?

Absolutely! Just change the `maxReviews` parameter in your input to whatever number you need. Set to `0` for unlimited.

#### Is this scraper safe to use?

Yes! We use efficient API calls that mimic normal traffic patterns to ensure reliability and safety.

### 🔗 Related Scrapers

**Need another review app?** The [Shopify review scraper for Stamped.io, REVIEWS.io, Junip, Fera, Opinew and Rivyo](https://apify.com/stanvanrooy6/shopify-review-scraper) auto-detects the review app (Judge.me, Loox, Yotpo, Okendo and the six above) from a store or product URL and returns the same unified output.

**Using different review platforms?** Check out my other Shopify scrapers:

- **[Universal Shopify Review Scraper](https://apify.com/stanvanrooy6/shopify-review-scraper)** - Automatically detects platform and extracts all reviews.
- **[Yotpo Reviews Scraper](https://apify.com/stanvanrooy6/yotpo-scraper)** - Dedicated scraper for Shopify stores using Yotpo.
- **[Loox Reviews Scraper](https://apify.com/stanvanrooy6/loox-scraper)** - Dedicated scraper for Shopify stores using Loox.
- **[Judge.me Reviews Scraper](https://apify.com/stanvanrooy6/judge-me-scraper)** - Dedicated scraper for Shopify stores using Judge.me.
- **[TikTok Shop Scraper](https://apify.com/stanvanrooy6/tiktok-shop-scraper)**: TikTok Shop reviews, star ratings and product data, up to 25,000 reviews per product. Same review schema.

***

Built with ❤️ for the Apify community

If this Actor saved you time, a rating on its Apify Store page helps other users find it.

# Actor input Schema

## `startUrl` (type: `string`):

Enter a Shopify store URL to get all reviews, or a product URL to get reviews for that specific product.

Examples:
• Store-wide: speargun.com, https://speargun.com
• Product-specific: https://speargun.com/products/mahogany-competition-series-riffe-spearfishing-speargun

## `maxReviews` (type: `integer`):

How many reviews to collect. Leave empty or set to 0 for unlimited.

## `minRating` (type: `integer`):

Keep reviews within the inclusive star range. Leave blank for any rating.

## `maxRating` (type: `integer`):

Keep reviews within the inclusive star range. Leave blank for any rating.

## `reviewDateFrom` (type: `string`):

Optional ISO date (YYYY-MM-DD) or timestamp. Inclusive; date-only boundaries use UTC and the end date includes the entire day. Reviews with unknown dates are excluded.

## `reviewDateTo` (type: `string`):

Optional ISO date (YYYY-MM-DD) or timestamp. Inclusive; date-only boundaries use UTC and the end date includes the entire day. Reviews with unknown dates are excluded.

## `reviewText` (type: `string`):

Case-insensitive phrase in the title or body.

## `verifiedOnly` (type: `boolean`):

Exclude reviews without a confirmed verified-buyer flag.

## `mediaOnly` (type: `boolean`):

Keep reviews with at least one photo or video supplied by the review app.

## `maxScannedReviews` (type: `integer`):

Total source reviews checked across all URLs when filters are active. Stops work even if there are fewer matches than maxReviews. Rejected reviews are not saved or charged as results. Without filters this setting has no effect.

## `startUrls` (type: `array`):

Batch of URLs, merged with startUrl. Provide at least one URL in either field.

## `onlyNewReviews` (type: `boolean`):

Remember the reviews seen for each URL and return only new or edited reviews on later runs. The first run saves up to the maximum reviews per URL and records the rest of the store as known. Schedule the run to monitor stores. Skipped reviews are not charged.

## `monitorName` (type: `string`):

Optional. A separate memory for the same URLs, for example one list per client. Leave empty to use the default list. Only used with monitoring.

## Actor input object example

```json
{
  "startUrl": "https://speargun.com",
  "maxReviews": 100,
  "verifiedOnly": false,
  "mediaOnly": false,
  "maxScannedReviews": 10000,
  "onlyNewReviews": false
}
```

# Actor output Schema

## `reviews` (type: `string`):

One row per review. JSON; append ?format=csv or ?format=xlsx for other formats.

## `reviewsCsv` (type: `string`):

The same rows as a CSV download.

# 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 = {
    "startUrl": "https://speargun.com"
};

// Run the Actor and wait for it to finish
const run = await client.actor("stanvanrooy6/okendo-scraper").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 = { "startUrl": "https://speargun.com" }

# Run the Actor and wait for it to finish
run = client.actor("stanvanrooy6/okendo-scraper").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 '{
  "startUrl": "https://speargun.com"
}' |
apify call stanvanrooy6/okendo-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,stanvanrooy6/okendo-scraper"
        }
    }
}
```

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/f0fttXETy2wTi6VU0/builds/8FCFhaUacsTAkOfVU/openapi.json
