# Byrna Reviews Extractor (`kawsar/byrna-reviews-extractor`) Actor

Extract detailed customer reviews, ratings, sentiments, and topics from Byrna.com product pages in real time. Perfect for market research, sentiment analysis, and competitor tracking.

- **URL**: https://apify.com/kawsar/byrna-reviews-extractor.md
- **Developed by:** [Kawsar](https://apify.com/kawsar) (community)
- **Categories:** E-commerce, Automation, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.50 / 1,000 results

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/platform/actors/running/actors-in-store#pay-per-event

## 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

## Byrna Reviews Extractor

Extract structured, analysis-ready customer reviews from any Byrna.com product page — including ratings, sentiment scores, verified buyer status, key topics, and reviewer-uploaded images.

Built for market researchers, e-commerce analysts, product teams, and competitive intelligence workflows.

---

### What This Actor Does

This actor crawls Byrna product pages and collects all publicly visible customer reviews in structured JSON format. It supports batch processing, pagination, and configurable limits so you can pull exactly the data you need — from a single product to your entire catalog.

Each extracted review includes:

- Star rating (1–5)
- Full review text and title
- Reviewer display name
- Verified buyer flag
- Sentiment score (–1.0 to +1.0)
- Helpful / not helpful vote counts
- Key topic extraction with supporting sentences
- Reviewer-uploaded product image URLs
- Review date (ISO 8601)

---

### Use Cases

- **Competitive & brand analysis** — understand how customers talk about Byrna products
- **Sentiment tracking** — monitor rating trends over time by re-running the actor
- **Product research** — surface common complaints, praise, and feature mentions automatically
- **Dataset building** — export clean JSON to Google Sheets, BigQuery, S3, or any downstream tool via Apify integrations
- **Review moderation support** — flag low-rated or negative-sentiment reviews for manual review

---

### How to Use

1. **Find Products** — go to byrna.com or byrna.ca and copy the full product URL or just the product handle (e.g., `byrna-sd-non-lethal-self-defense-pistol`).
2. **Configure Input** — paste one or more URLs or handles into the `urls` field. Optionally set `itemLimit` and `requestTimeoutSecs`.
3. **Run the Actor** — click **Start** and the actor handles the rest: product ID resolution, pagination, and structured output.
4. **Download Results** — export your dataset in JSON, CSV, JSONL, XML, or open it directly in Google Sheets via the Apify integration.

---

### Input

Configure the actor from the Apify Console or via the API.

| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| `urls` | `array<string>` | **Yes** | — | One or more Byrna product page URLs or product handles |
| `itemLimit` | `integer` | No | `10` | Maximum reviews to extract **per product**. Range: 1–1000 |
| `requestTimeoutSecs` | `integer` | No | `30` | Per-request timeout in seconds. Range: 5–120 |

#### Input Examples

**Minimal — single product URL:**
```json
{
  "urls": [
    "https://byrna.com/products/byrna-sd-non-lethal-self-defense-pistol"
  ]
}
````

**Multiple products with custom limits:**

```json
{
  "urls": [
    "https://byrna.com/products/byrna-sd-non-lethal-self-defense-pistol",
    "https://byrna.com/products/byrna-le-launcher",
    "byrna-hd-extra-power-kit"
  ],
  "itemLimit": 500,
  "requestTimeoutSecs": 60
}
```

> **Tip:** You can pass a product handle (the URL slug after `/products/`) directly — the actor resolves it to a full URL automatically.

***

### Output

Results are stored in the Apify dataset. Each row represents one customer review.

#### Output Schema

| Field | Type | Description |
|---|---|---|
| `product_id` | `string` | Shopify product identifier |
| `review_id` | `integer` | Unique review identifier |
| `rating` | `integer` | Star rating from 1 (lowest) to 5 (highest) |
| `review_date` | `string` | ISO 8601 timestamp of when the review was submitted |
| `review_title` | `string` | Subject line of the review |
| `review_text` | `string` | Full body of the review |
| `reviewer_name` | `string` | Reviewer's public display name (`"Anonymous"` if not available) |
| `verified_buyer` | `boolean` | `true` if the reviewer purchased the product |
| `sentiment` | `number` | Sentiment score: –1.0 (very negative) → +1.0 (very positive) |
| `votes_up` | `integer` | Count of users who found this review helpful |
| `votes_down` | `integer` | Count of users who found this review unhelpful |
| `topics` | `object` | Key topics detected in the review with supporting sentence excerpts |
| `images` | `array<string>` | URLs of images uploaded by the reviewer |

#### Sample Output Record

```json
{
  "product_id": "6886082838595",
  "review_id": 336452009,
  "rating": 5,
  "review_date": "2022-02-10T17:37:27.000Z",
  "review_title": "I love it…",
  "review_text": "I love it… I have guns but just the feeling of a non-lethal way it's amazing and less headaches",
  "reviewer_name": "Jose A.",
  "verified_buyer": true,
  "sentiment": 0.9295,
  "votes_up": 395,
  "votes_down": 70,
  "topics": {
    "gun": {
      "name": "gun",
      "sentence": "I love it… I have guns but just the feeling of a non-lethal way it's amazing and less headaches"
    }
  },
  "images": [
    "https://cdn-yotpo-images-production.yotpo.com/Review/336452009/241428524/original.jpg"
  ]
}
```

***

### Supported URL Formats

| Format | Example |
|---|---|
| Full US store URL | `https://byrna.com/products/byrna-sd-non-lethal-self-defense-pistol` |
| Full CA store URL | `https://byrna.ca/products/byrna-sd-non-lethal-self-defense-pistol` |
| Product handle only | `byrna-sd-non-lethal-self-defense-pistol` |

***

### Performance & Limits

- Reviews are fetched in pages of 100; pagination is handled automatically.
- `itemLimit` caps the total reviews collected per product (maximum 1000).
- Multiple products in one run are processed sequentially.
- If one product fails (invalid URL, product not found), the actor logs the error and continues with remaining products.
- No proxies need to be purchased or configured separately.

***

### Export Options

After a successful run, export your dataset from the Apify Console in:

| Format | Best For |
|---|---|
| **JSON** | Developer pipelines, APIs |
| **CSV** | Excel, Google Sheets |
| **JSONL** | Streaming data pipelines |
| **XML** | Legacy integrations |

Connect directly to Google Sheets, Zapier, Make (Integromat), Slack, and other platforms via Apify's built-in integrations.

***

### Error Handling

| Situation | Behavior |
|---|---|
| No valid URLs provided | Actor fails immediately with a clear actionable message |
| Product page not found (404) | Logs error, skips product, continues with remaining |
| Access temporarily unavailable (403/429) | Logs error, skips product, continues with remaining |
| Partial review page returned | Stops pagination for that product, saves what was collected |

***

### FAQs

#### Do I need to configure proxies?

No. The actor has built-in access infrastructure that handles all routing automatically. No additional configuration is required.

#### Can I scrape both US (byrna.com) and Canadian (byrna.ca) stores?

Yes. Paste URLs from either store or enter product handles — the actor handles domain routing for both.

#### Is there a review limit?

You control the limit with the `itemLimit` parameter (1–1000 per product). The actor also stops naturally when all available reviews have been collected.

#### What happens if a product URL is invalid?

The actor logs a warning for that product and moves on to the next one. Your run will complete with data for all valid products.

***

### Actor Bio

**Byrna Reviews Extractor** is a purpose-built Apify actor for collecting publicly available customer reviews from [byrna.com](https://byrna.com) — the leading brand in non-lethal self-defense launchers. Unlike generic scrapers, this actor resolves product identifiers dynamically from each page and retrieves full structured review data including sentiment scores, topic classification, and media attachments.

Designed for production use: per-product errors do not abort the full run, and pagination is handled transparently so you always get the complete review dataset up to your configured limit.

***

### Legal & Terms of Use

This actor collects only **publicly visible** review content from byrna.com and byrna.ca. It does not access any private, authenticated, or gated content. Users are responsible for ensuring their use of extracted data complies with Byrna's [Terms of Service](https://byrna.com/policies/terms-of-service) and applicable data protection regulations.

# Actor input Schema

## `urls` (type: `array`):

Required. A list of Byrna product URLs or handles to scrape reviews from.

## `itemLimit` (type: `integer`):

Maximum number of reviews to extract per product.

## `requestTimeoutSecs` (type: `integer`):

Per-request timeout in seconds for accessing target web pages and APIs.

## Actor input object example

```json
{
  "urls": [
    "https://byrna.com/products/byrna-sd-non-lethal-self-defense-pistol"
  ],
  "itemLimit": 10,
  "requestTimeoutSecs": 30
}
```

# 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 = {
    "urls": [
        "https://byrna.com/products/byrna-sd-non-lethal-self-defense-pistol"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("kawsar/byrna-reviews-extractor").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 = { "urls": ["https://byrna.com/products/byrna-sd-non-lethal-self-defense-pistol"] }

# Run the Actor and wait for it to finish
run = client.actor("kawsar/byrna-reviews-extractor").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 '{
  "urls": [
    "https://byrna.com/products/byrna-sd-non-lethal-self-defense-pistol"
  ]
}' |
apify call kawsar/byrna-reviews-extractor --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Byrna Reviews Extractor",
        "description": "Extract detailed customer reviews, ratings, sentiments, and topics from Byrna.com product pages in real time. Perfect for market research, sentiment analysis, and competitor tracking.",
        "version": "0.0",
        "x-build-id": "cVNXlVhwpKrwQ9rR3"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/kawsar~byrna-reviews-extractor/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-kawsar-byrna-reviews-extractor",
                "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/kawsar~byrna-reviews-extractor/runs": {
            "post": {
                "operationId": "runs-sync-kawsar-byrna-reviews-extractor",
                "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/kawsar~byrna-reviews-extractor/run-sync": {
            "post": {
                "operationId": "run-sync-kawsar-byrna-reviews-extractor",
                "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": {
                    "urls": {
                        "title": "Product URLs / Handles",
                        "type": "array",
                        "description": "Required. A list of Byrna product URLs or handles to scrape reviews from.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "itemLimit": {
                        "title": "Max Reviews per Product",
                        "minimum": 1,
                        "maximum": 1000,
                        "type": "integer",
                        "description": "Maximum number of reviews to extract per product.",
                        "default": 10
                    },
                    "requestTimeoutSecs": {
                        "title": "Request Timeout (seconds)",
                        "minimum": 5,
                        "maximum": 120,
                        "type": "integer",
                        "description": "Per-request timeout in seconds for accessing target web pages and APIs.",
                        "default": 30
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
