# Opera Add-ons Extension Catalog Scraper (`automation-lab/opera-addons-extension-catalog`) Actor

Collect public Opera extension catalog snapshots from category, search and detail URLs, including ratings, authors, versions, permissions and listing positions.

- **URL**: https://apify.com/automation-lab/opera-addons-extension-catalog.md
- **Developed by:** [Automation Lab](https://apify.com/automation-lab) (community)
- **Categories:** Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.16 / 1,000 item extracteds

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

## Opera Add-ons Extension Catalog Scraper

Collect public Opera browser extension snapshots for competitor research and software-market analysis. Start from catalog, category, search or individual extension URLs and receive structured records with titles, authors, ratings, public versions and source provenance.

### What does this Actor do?

It follows Opera Add-ons listing pages and optionally opens each extension's public detail page. Each unique extension slug produces one dataset row per run. Listing position, category provenance and collection time help you compare weekly exports without confusing a search position with an installation count.

### Who is it for?

- Extension developers researching competing products and release activity.
- Market analysts comparing categories and public rating-count growth.
- Data teams building a repeatable extension catalog feed.

### Why use this Actor?

Preserve where an extension was discovered, not just its current profile. Choose lightweight list-only snapshots or public detail enrichment without logging in, downloading binary packages or supplying a paid data API. Missing public values remain null; the Actor never estimates installs.

### Getting started

1. Paste an Opera extension category, search or detail URL.
2. Set a global maximum number of extensions.
3. Keep detail enrichment enabled for versions, author and permissions.
4. Start the Actor, then export the dataset as JSON, CSV or Excel.

```json
{
  "startUrls": ["https://addons.opera.com/en/extensions/category/privacy-security/"],
  "locale": "en",
  "sort": "popular",
  "maxExtensions": 10,
  "includeDetails": true
}
```

### Inputs

| Field | Default | Meaning |
|---|---|---|
| `startUrls` | Extension catalog when omitted | 1–100 Opera catalog, category, search or detail URLs; empty arrays fail. |
| `locale` | `en` | Replaces URL locale on every source. Supported values appear in the input form. |
| `sort` | `popular` | Catalog/category ordering: `popular`, `new`, `top-rated`. Overrides URL order. |
| `maxExtensions` | 50 | Global cap of 1–10,000 unique extension slugs. No unlimited mode. |
| `includeDetails` | true | Fetch public details for discovered extensions. Direct detail URLs always return details. |

Search URL example: `https://addons.opera.com/en/search/?query=privacy`.
Developer searches such as `https://addons.opera.com/en/search/?developer=gorhill` are also accepted.
Search results use Opera relevance, regardless of `sort`; search URLs containing `order` are rejected instead of silently ignoring it. Search type is restricted to extensions.

Only public HTTPS URLs on `addons.opera.com` are accepted. Theme pages, package URLs, external hosts and unknown query parameters fail validation. Supported query parameters are `query`, `developer`, `order`, `page`, `tag` and extension-only `type`.

### Output fields

| Field | Description |
|---|---|
| `extensionId`, `slug` | Opera URL slug, used as stable identity; not a numeric marketplace ID. |
| `title`, `author` | Public title and developer byline. |
| `category`, `summary` | Detail category and first description paragraph, or list summary without enrichment. |
| `version`, `updatedAt` | Public version and update date in the displayed page language, not an ISO conversion. |
| `rating`, `ratingCount` | Public aggregate rating and number of ratings, not text reviews or installs. |
| `permissions` | Public permission statements; null without details, empty array if none are listed. |
| `sourceUrl` | Extension detail URL. |
| `listingUrl`, `listingPageUrl` | Normalized first input listing and exact paginated page where found. |
| `listingPosition` | One-based extension-card position across pages visited for that input, before deduplication. |
| `listingCategory` | Category slug from the input URL; separate from the extension category. |
| `locale`, `sort`, `observedAt` | Requested locale, actual ordering mode and UTC snapshot timestamp. |

Direct detail records have null listing provenance and position. Duplicate slugs across inputs retain only their first occurrence. Starting at `page=2` counts positions from the first page visited, not from an unvisited page 1. Positions are not global popularity ranks.

### Output example

Public values below were observed on a current local detail test; the collection timestamp illustrates the format.

```json
{
  "extensionId": "ublock",
  "slug": "ublock",
  "title": "uBlock Origin",
  "author": "gorhill",
  "category": "Privacy & Security",
  "version": "1.75.0",
  "updatedAt": "Sept. 18, 2026",
  "rating": 5,
  "ratingCount": 5530,
  "sourceUrl": "https://addons.opera.com/en/extensions/details/ublock/",
  "listingUrl": null,
  "listingPageUrl": null,
  "listingPosition": null,
  "listingCategory": null,
  "locale": "en",
  "sort": null,
  "observedAt": "2026-10-29T07:00:00.000Z"
}
```

The example omits the longer summary and permission list for readability. All fields are available in JSON exports. List pages sometimes omit exact ratings even when a rounded star graphic exists; missing numeric values remain null rather than being inferred from CSS.

### How much does it cost to collect Opera extension snapshots?

Pricing is pay per event: a $0.005 start event per run, plus one `item` event per unique extension snapshot saved. Detail enrichment has no separate event charge. Failed, duplicate and empty records incur no item charge; a started run can still incur the start fee.

| Apify Store spend tier | Per extension snapshot |
|---|---:|
| FREE | $0.00414 |
| BRONZE | $0.0036 |
| SILVER | $0.002808 |
| GOLD | $0.00216 |
| PLATINUM | $0.00216 |
| DIAMOND | $0.00216 |

At BRONZE, 10 snapshots cost approximately $0.041, 100 cost $0.365 and 1,000 cost $3.605, including the start event once. At FREE, 10 snapshots cost about $0.0464. These are invoice examples, not payout promises; the live Pricing tab and actual saved count are authoritative. Spend tiers follow Apify's qualifying monthly Store spend, not a private per-Actor volume discount.

### Limits and troubleshooting

The Actor reads public extension HTML only. It does not collect reviews, historical changes, install estimates, private developer dashboards or binary packages. Built-in Opera entries may have fewer public fields than installable extensions.

Catalog coverage depends on Opera's pagination and availability. A cap is an upper bound, not a promise that every query has that many results. Locale pages can retain untranslated text. Save successive runs yourself to calculate changes; the Actor does not maintain historical state or send alerts.

Requests are sequential and bounded: transient network errors, HTTP 429 and 5xx are retried at most twice. Other HTTP errors and changed page markup fail the run honestly. Earlier rows can remain in the dataset after a later failure; treat them as partial output, not a complete snapshot. There is no automatic paid proxy fallback.

If a URL fails, check its extension/category/search path and supported parameters. If a query returns zero rows, check it in Opera's public search. A recognized no-results page is a valid empty outcome; challenge pages are not.

### Integrations

Export JSON/CSV/Excel from Apify, or send completed datasets to Google Sheets, Make, Zapier or an HTTP webhook using Apify integrations. For weekly tracking, schedule the same category input and join exports on `slug`, retaining `observedAt`. Compare `ratingCount` or `version` between snapshots; do not interpret rating-count growth as installs.

### API usage

Use your own Apify token in the environment. These examples start a paid run.

#### cURL

```bash
curl -X POST 'https://api.apify.com/v2/acts/automation-lab~opera-addons-extension-catalog/run-sync-get-dataset-items' \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"maxExtensions":10,"sort":"new","includeDetails":true}'
```

#### JavaScript

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/opera-addons-extension-catalog').call({ maxExtensions: 10 });
const { items } = await client.dataset(run.defaultDatasetId).listItems({ limit: 10 });
console.log(items);
```

#### Python

```python
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/opera-addons-extension-catalog').call(run_input={'maxExtensions': 10})
print(client.dataset(run['defaultDatasetId']).list_items(limit=10).items)
```

### MCP setup

```bash
claude mcp add --transport http apify \
  'https://mcp.apify.com?tools=automation-lab/opera-addons-extension-catalog'
```

Equivalent Claude Desktop, Cursor and VS Code configuration for clients supporting HTTP MCP:

```json
{"mcpServers":{"apify":{"url":"https://mcp.apify.com?tools=automation-lab/opera-addons-extension-catalog"}}}
```

Configure Apify authentication using your client's protected credential settings. Example prompt: “Collect 10 popular Opera privacy extensions and show their versions, rating counts and source URLs.”

Discover actual tool names and schemas using scoped `tools/list`. Actor selection also adds run/status/dataset/KV/abort tools; it is not exactly one tool. Discovery is read-only and not permission to execute. For an authorized invocation, start once and retain run and storage IDs. If still running, poll the same run with 2, 4, 8 then at most 10 seconds between checks and a 120-second deadline; client timeouts must exceed the selected server wait plus transport margin. At deadline report pending and the run ID. After a timeout recover that run, never start another merely to poll.

After success, fetch dataset pages with explicit `limit`, `offset` and selected fields. A suggested consumer budget is 20 source rows per page, at most 100 rows and 64 KiB serialized UTF-8 across pages admitted to model context. Enforce bytes host-side before injection; omit or summarize oversized content with disclosure. If the client cannot intercept responses, do not claim a hard byte guarantee. Report returned rows, next source offset and truncation. Keep full exports in storage. These are consumer context limits, not Actor collection limits. No universal token-saving claim is made.

### Legality and data handling

Use public data in accordance with applicable laws and Opera's terms. This independent tool is not affiliated with or endorsed by Opera. Public visibility is not permission to reuse copyrighted descriptions without considering their license.

Failed operations send sanitized diagnostic input, exceptions and Actor/build/run IDs to our private GlitchTip service for repair. Secret fields and URL query strings are removed; diagnostic reports are retained for 30 days. No customer login is needed or accepted. The Actor uses no AI at runtime and sends no input or scraped data to an AI provider. Apify hosts the per-run dataset, statistics and logs under your account's retention settings; delete those stores in Console/API when no longer needed. No cross-run session or catalog cache is maintained. GlitchTip is the only additional diagnostic recipient. For questions or defects, open an issue in this Actor's Apify Issues tab.

### FAQ

**Can it track changes automatically?** Schedule runs and compare exported snapshots downstream; it does not calculate deltas itself.

**Why is a field null?** Opera may not publish it, or list-only mode did not fetch its detail page. Rounded stars are not treated as exact numeric ratings.

**Can I collect Chrome or Firefox extensions?** No. This Actor is specifically for public Opera Add-ons extension pages.

**Why did a run fail after saving some rows?** A later source page or request failed. Inspect the error and use the existing dataset only as partial evidence.

### Related Actors

For a separate software marketplace, [Apple App Store Scraper](https://apify.com/automation-lab/apple-app-store-scraper) supports app-intelligence workflows. For user feedback on Chrome extensions, see [Chrome Web Store Reviews Scraper](https://apify.com/automation-lab/chrome-web-store-reviews-scraper). These are distinct data sources, not alternative inputs to this Actor.

# Changelog

This Actor's version history is a separate document: https://apify.com/automation-lab/opera-addons-extension-catalog/changelog.md

# Actor input Schema

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

One to 100 public Opera extension catalog, category, search or detail URLs. Omit to browse the extension catalog. Explicit empty arrays fail. Inputs are processed in order and duplicate slugs retain the first occurrence. Only query, developer, order, page, tag and extension-only type URL parameters are accepted. Themes, packages and external URLs are rejected.

## `locale` (type: `string`):

Replaces the locale segment on every supplied URL. Public text and update dates remain in Opera's displayed language; untranslated source text may remain English.

## `sort` (type: `string`):

Opera server-side order for catalog/category URLs; overrides URL order. Search URLs always use Opera relevance and must not include order. Direct detail URLs have no ordering. Top-rated maps to Opera rated, not a client-side re-sort.

## `maxExtensions` (type: `integer`):

Global cap on unique extension slugs saved across all inputs and pages, after deduplication. Zero/unlimited is not supported. Stops requesting new pages/details once reached. Available source results, runtime and billing limits may stop earlier.

## `includeDetails` (type: `boolean`):

For catalog/search results, fetch each extension page for author, category, version, displayed update date, permissions and exact public rating. False uses list fields only; unavailable fields are null, not inferred from CSS rating classes. Direct detail URLs always return their details.

## Actor input object example

```json
{
  "startUrls": [
    "https://addons.opera.com/en/extensions/category/privacy-security/"
  ],
  "locale": "en",
  "sort": "popular",
  "maxExtensions": 10,
  "includeDetails": true
}
```

# Actor output Schema

## `dataset` (type: `string`):

Unique public extension records in the default dataset.

## `statistics` (type: `string`):

Saved item, request, byte and retry counters.

# 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 = {
    "startUrls": [
        "https://addons.opera.com/en/extensions/category/privacy-security/"
    ],
    "maxExtensions": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/opera-addons-extension-catalog").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 = {
    "startUrls": ["https://addons.opera.com/en/extensions/category/privacy-security/"],
    "maxExtensions": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/opera-addons-extension-catalog").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 '{
  "startUrls": [
    "https://addons.opera.com/en/extensions/category/privacy-security/"
  ],
  "maxExtensions": 10
}' |
apify call automation-lab/opera-addons-extension-catalog --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/opera-addons-extension-catalog"
        }
    }
}
```

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/kEd8kKyQaj4AkDBHB/builds/Q2pO4YJ6m4ToxcpuB/openapi.json
