# Changelog of Chrome Web Store Scraper: Extensions & Permissions (`succinct_glider/chrome-web-store-extensions`) Actor

- **URL**: https://apify.com/succinct_glider/chrome-web-store-extensions/changelog.md
- **Full Actor documentation**: https://apify.com/succinct_glider/chrome-web-store-extensions.md

## Changelog

### Unreleased

- Store page: title `Chrome Web Store Scraper: Extensions & Permissions`, shorter description, a description on the input form, the price in the README intro and pricing section, and a section on using the Actor through the API and integrations.
- The "Maximum cost per run reached" message is now logged once instead of twice when the cost limit stops the run.
- The output fields are unchanged.

### 0.6.3 — 2026-09-16

- Stopping on the cost limit used `autoscaledPool.abort()`, which returns before the running handlers end: the run could write its `SUMMARY` and exit while an extension was still saving its state. The crawl now stops with `crawler.stop()`, which lets running pages finish first.
- Extension pages read at once could all pass the cost-limit check for the last item. The SDK counts an item only once its push completes and drops the extra ones silently, while their change-tracking state was saved as if they had been delivered, so `onlyChanges` would never report them. The budget is now re-checked right before each push, counting the pushes still in flight.
- The output fields are unchanged.

### 0.6 — 2026-09-15

- Category discovery (`mode: "categories"`): scan the public pages of up to 18 store categories, each listing its top 32 extensions, and scrape the matching ones. Filters `minUsers`, `minRating`, `keyword` and `maxPermissionRiskLevel` are applied to the category listing before any extension page is read, so non-matching extensions cost nothing. `maxItems` caps the number of extensions across categories.
- `extensions` is no longer required (it is used with the default `mode: "extensions"`).
- `SUMMARY.discovery` reports requested, scanned and unreadable categories, listed and matching extensions. A run fails only if no category page could be read; no match for the filters is a successful run.
- The output fields are unchanged.

### 0.5 — 2026-09-15

- Change tracking (`trackChanges`): each extension is compared with its state from the previous tracked run, kept in a key-value store of the user's account (`stateStoreName`). New output fields `changeStatus` (`new`, `changed`, `unchanged`), `changedFields`, `previousValues` and `previousScrapedAt`, all `null` when tracking is off. Rating moves below 0.01 are ignored without hiding slow drifts.
- `onlyChanges`: unchanged extensions are not saved to the dataset, so they are not charged.
- New **Changes** view in the Output tab; `SUMMARY.changes` counts extensions per status, and the final message lists them.

### 0.4 — 2026-09-15

- New permission audit fields, computed from the manifest without extra requests: `allSitesAccess` (host permissions or content scripts covering every website), `sensitivePermissions` (required permissions reaching browsing data, network traffic or browser control) and `permissionRiskLevel` (`low`, `medium`, `high`). They are shown first in the Permissions view.
- Removed or unlisted extensions that the store serves as a generic page (HTTP 200, title "Chrome Web Store") are now reported in `notFoundIds` instead of `unreadableIds`, so `unreadableIds` only signals a possible page layout change. On 500 random extensions, all 13 previously unreadable pages were of this kind. Warnings for unreadable pages include the HTTP status and page title.
- README: ready-to-use inputs for competitor tracking, permission audits and market research.

### 0.3 — 2026-09-15

- The data quality check no longer uses `users`: small extensions show no user count, so a run on a few new extensions could fail wrongly. It now checks `version` and `updatedAt` only, and `SUMMARY.missingKeyFields` lists these two fields.
- Minimum memory raised to 512 MB: at 256 MB a 500-extension run ran out of memory (peak about 220 MB at 512 MB).

### 0.2 — 2026-09-15

- Runs no longer fail because of the input: an input without any valid extension ID or URL, or extensions that were all removed from the store, now end successfully with an explanatory status message and the `SUMMARY` record (warning in the log).
- New data quality check: the run fails when `users`, `version` or `updatedAt` is missing on more than half of the scraped extensions, a sign that the store page layout changed. Items already scraped stay in the dataset.
- `SUMMARY` gains `missingKeyFields` (count of scraped extensions without each key field).
- A run where no extension could be read for technical reasons (blocking, network errors, unreadable pages) still fails.

### 0.1 — 2026-09-14

First public version.

- Scrapes public Chrome Web Store extension detail pages from extension IDs or store URLs (current `chromewebstore.google.com` and legacy `chrome.google.com/webstore` domains). URLs from other websites are rejected; invalid entries are skipped with a warning, and the run fails if no valid entry remains.
- Duplicate entries are scraped once; `maxItems` (default 100, max 5,000) limits the number of extensions.
- Output: users, precise rating, rating count, category path and displayed category name (`categoryName`), version, update date, size as displayed and converted to bytes (`sizeBytes`, approximate because the store rounds it), languages, Featured badge, EU trader status, website / support / privacy policy URLs, minimum Chrome version, manifest version and permissions (required, optional, host), icon, screenshots and videos.
- The Overview view of the Output tab shows the category name.
- Full description is optional (`includeDescription`, enabled by default).
- Developer contact data (email, address, phone, personal name, manifest author) is never collected.
- Only detail pages are requested (reviews, search and related pages are disallowed by robots.txt), with plain HTTP requests and no browser: 5 in parallel, at most about 120 per minute. Default memory 512 MB.
- Progress is shown in the run status message (`Scraped 42 of 100 extensions…`), followed by a final summary message.
- A `SUMMARY` record in the default key-value store (Run summary in the Output tab) lists requested and scraped counts, not found, unreadable and failed extension IDs, invalid input entries (first 100) and whether the cost limit was reached.
- Removed or unreadable extensions are skipped without retries.
- The crawl stops as soon as the user's maximum cost per run is reached (pay-per-event).
- A run that scrapes no extension at all fails explicitly, so schedules and integrations detect it. A run stopped by the maximum cost per run is not failed.
- Known, accepted: moderate advisory GHSA-528h-pc64-c93x on `stream-json` (dependency of `@crawlee/core`), the source of all 5 moderate `npm audit --omit=dev` alerts. Forcing the patched 3.6.0 breaks Crawlee at runtime (module layout changed), and the Actor never feeds user-controlled JSON to it. Upgrade when Crawlee ships a fix.
