# Shopware Store Scraper — Prices and Compatibility (`atesen-software/shopware-store-extensions-scraper`) Actor

Scrape store.shopware.com: extension name, producer, price and rental plans with currency, compatible Shopware versions, rating, reviews, last update, version, languages and description. Filter by search term, category and Shopware version. No login, no proxy. Pay per result — see the Pricing tab.

- **URL**: https://apify.com/atesen-software/shopware-store-extensions-scraper.md
- **Developed by:** [Atesen Software](https://apify.com/atesen-software) (community)
- **Categories:** E-commerce
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$5.00 / 1,000 successful extension results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

Scrape the Shopware Store: extension prices and rental plans, compatible Shopware versions, ratings, reviews, last update and languages. No login needed.

### Shopware Store Extensions Scraper (prices, versions, ratings)

Give it search terms, store categories or single extension pages from **store.shopware.com** and get one row per extension: **name, URL, producer name, price and rental plans with currency, compatible Shopware versions, rating, number of reviews, last update, version, languages and short description**. It reads the public store pages, so no account, no API key and no proxy are needed.

- **Version filter**: keep only extensions that support the Shopware version you run, for example `6.6` (any 6.6.x.y) or `6.7.2.0`.
- **Real prices, never guessed**: free is saved only when the store says "Free". A page without a readable price gives an empty price, never `0`. Extensions that are not released yet are marked `coming_soon`.
- **Rental plans**: the Shopware Store rents extensions. Monthly and annual plans are saved with their own price and interval.
- **Polite**: about one request per second, the store's `robots.txt` is read first, retries with back-off, the actor slows down when the store reports that its request allowance is running low, and it stops when the store stops answering extension pages (3 in a row) instead of asking again.
- **Never crashes on a bad input**: a wrong URL, a missing extension or a blocked page becomes one free `status` row that says why.
- **No reviews, no contacts**: the only name saved is the producer's name as the store prints it. Most producers are companies; a sole trader can be listed under their own name. Reviews, reviewer names, support contacts and partner pages are not read, and e-mail addresses are removed from text fields.

### Use cases

- **Competitor and market research**: which extensions exist in a category, what they cost per month, how well they are rated and how often they are updated.
- **Compatibility checks**: find extensions that already support the newest Shopware version before you upgrade a shop.
- **Agency catalogues**: keep a dated list of the extensions you recommend, with price, version and last update.
- **Partner and producer monitoring**: watch new releases, price changes and ratings of the extensions you sell or depend on.

### Input

| Field | Description |
|---|---|
| `searchTerms` | Words for the store's own search, for example `seo` or `paypal`. 24 extensions per page, best match first. The store also returns partial matches. |
| `startUrls` | English store URLs on `store.shopware.com/en/`: a category or listing (`/en/extensions/integration/legal-security/`), a search (`/en/search?search=theme`) or one extension page (`/en/<code>/<name>.html`). Other languages are not supported. |
| `shopwareVersions` | Optional. Keep extensions whose compatibility range contains at least one of these versions (`6.6`, `6.7.2.0`). Needs the extension page of every candidate. |
| `maxItems` | Stop after this many extension rows in total. Default 50. `0` = no limit (the pages limit still applies). |
| `maxListingPages` | Listing pages read per search term or listing URL. Default 5, 24 extensions per page. |
| `includeDetails` | Default on. One extra request per extension for rental plans, compatible versions, last update, version, languages, downloads and category. Off = 24 extensions per request with name, producer, price, rating and short description. A version filter always reads the extension pages. |
| `includeSourceInfo` | Default on. One free `source` row per search term, listing or extension URL. |

```json
{
  "searchTerms": ["seo"],
  "shopwareVersions": ["6.7"],
  "maxItems": 8,
  "maxListingPages": 1
}
```

### Output

One row per extension. This is a real row from a run on 24 October 2026.

```json
{
  "type": "extension",
  "name": "SEO Professional",
  "url": "https://store.shopware.com/en/dreis43878114545m/seo-professional.html",
  "extensionCode": "dreis43878114545m",
  "producer": "Dreischild GmbH",
  "category": "SEO Optimization",
  "price": 33.25,
  "priceInterval": "month",
  "currency": "EUR",
  "priceType": "rental",
  "isFree": false,
  "priceNetOfVat": true,
  "rentalPlans": [
    { "plan": "Annually", "price": 399, "interval": "year", "pricePerMonth": 33.25 },
    { "plan": "Monthly", "price": 39.9, "interval": "month", "pricePerMonth": 39.9 }
  ],
  "compatibleVersions": "6.1.4 - 6.7.15.1",
  "compatibleFrom": "6.1.4",
  "compatibleTo": "6.7.15.1",
  "hosting": null,
  "matchesVersions": null,
  "ratingValue": 4.28,
  "reviewsCount": 29,
  "downloads": 2473,
  "downloadsText": "2,473",
  "lastUpdate": "2026-10-19",
  "publicationDate": "2020-03-30",
  "version": "6.15.92",
  "shortDescription": "Effective search engine optimization for Shopware 6 with SEO Professional through many SEO functions that expand the Shopware standard accordingly. Test now!",
  "languages": ["English", "German"],
  "detailsRead": true,
  "input": "https://store.shopware.com/en/dreis43878114545m/seo-professional.html",
  "scrapedAt": "2026-10-24T02:31:51.428Z"
}
```

How to read the price fields:

- `price` is the **lowest price per month** over all rental plans, in `currency` (EUR). An annual plan is shown as its monthly equivalent in `pricePerMonth`. `rentalPlans` lists every plan with the price you actually pay per `interval`.
- `priceType` is `free` (the store says "Free"), `rental`, or `coming_soon` (not released yet, price empty). If the price cannot be read, `price`, `priceType` and `isFree` are all `null`.
- `priceNetOfVat` is `true` when the page carries the store's note that prices are quoted net of VAT.
- `ratingValue` is empty and `reviewsCount` is `0` for an extension without reviews. Both are empty when the page shows no review section at all. With `includeDetails` off, a listing card without a rating badge gives empty `ratingValue` and empty `reviewsCount` (unknown, not 0).
- `compatibleVersions` is the range printed by the store. `hosting` lists `Cloud` or `Self-hosted` badges. If the page names no version range (some self-hosted listings), the version fields are empty.
- `downloads` is a number only when the store prints one; a value such as `<10` is kept as text in `downloadsText`.
- With `includeDetails` off, the fields that need the extension page (`category`, `rentalPlans`, `compatible*`, `hosting`, `matchesVersions`, `downloads`, `downloadsText`, `lastUpdate`, `publicationDate`, `version`, `languages`) are left out and `detailsRead` is `false`.

Free helper rows share the same dataset:

- `type: "source"`: one per input. `input`, `kind` (`search`, `listing` or `extension`), `shopwareVersions`, `listingPagesRead`, `entriesScanned`, `entriesInListing` (what the store says the listing holds), `skippedOtherVersion`, `skippedVersionUnknown`, `detailPagesFailed`, `itemsSaved`, `complete`. `complete` is `true` only when the whole listing was read: it is `false` when `maxItems`, `maxListingPages` or the cost limit stopped the run, or when a page could not be read (with a version filter this includes an extension page that failed), or when the run stopped early because the store stopped answering. A listing page that comes back without any extension cards inside the range the store announced counts as an unreadable page, not as the end of the listing.
- `type: "status"`: `status`, `input`, `url`, `httpStatus`, `message`.

Status values you may see: `invalid_input`, `invalid_url`, `unsupported_url`, `blocked_by_robots`, `fetch_failed`, `access_denied`, `not_found`, `extension_not_found`, `detail_failed`, `listing_parse_failed`, `no_results`, `no_version_match`, `version_mismatch`, `version_unknown`, `error` (an unexpected failure; the run then ends as failed).

A status row for a failed extension page inside a listing says whether the extension was still saved from its listing card (and counts as a result) or left out. If 3 extension pages in a row cannot be read (HTTP 403, 429, 5xx or a page that is not an extension page; a 404 does not count), the run stops, keeps what it saved, writes one more status row that says so, and marks the `source` row `complete: false`.

```json
{
  "type": "status",
  "status": "extension_not_found",
  "input": "https://store.shopware.com/en/nosuchcode123/does-not-exist.html",
  "message": "extension nosuchcode123 does not exist in the store (HTTP 404). Not charged.",
  "url": "https://store.shopware.com/en/nosuchcode123/does-not-exist.html",
  "httpStatus": 404,
  "scrapedAt": "2026-10-24T02:31:52.440Z"
}
```

A real `source` row (search `seo`, version filter `6.7`, one listing page): 15 extensions read, 6 supported other versions, 1 gave no version range, 8 saved, `complete: false` because only the first page was read.

```json
{
  "type": "source",
  "input": "seo",
  "kind": "search",
  "shopwareVersions": ["6.7"],
  "listingPagesRead": 1,
  "entriesScanned": 15,
  "entriesInListing": 286,
  "skippedOtherVersion": 6,
  "skippedVersionUnknown": 1,
  "detailPagesFailed": 0,
  "itemsSaved": 8,
  "complete": false,
  "scrapedAt": "2026-10-24T02:31:18.432Z"
}
```

### Limits

- Only English store pages (`/en/`) are read. The store's search ranks best matches first and also returns partial matches, so check the first rows.
- A search or category is read in the store's own ranking, up to `maxListingPages` pages. The `source` row tells you how many extensions the store lists and whether the whole listing was read.
- A version filter has to open the page of every candidate, so a filtered scan of a large category takes about one second per extension.
- If an extension page cannot be read, the extension is still saved from its listing card (without the page-only fields) and a status row (`detail_failed`, `extension_not_found`, `access_denied`, `fetch_failed` or `blocked_by_robots`) names it. That partial row is still one result. With a version filter such an extension is left out, because its versions cannot be checked.
- Prices are the store's public prices, quoted net of VAT. Discounts, trial months and in-app purchases are not read.
- The actor stays out of private areas: cart, account, wishlist and the store's internal widget routes are never requested.

### FAQ

**Do I need a Shopware account, an API key or a proxy?** No. The actor reads the public pages of store.shopware.com. If the store ever answers with a block page (HTTP 403), you get a free `access_denied` status row and nothing is charged. The actor does not try to get around a block.

**How does the Shopware version filter work?** `6.6` matches every extension whose range contains any 6.6.x.y version, `6.7.2.0` matches ranges containing exactly that release. The range is read from the extension page. Extensions whose page prints no range cannot be checked: they are left out and counted in `skippedVersionUnknown` of the `source` row.

**What does `price` mean when an extension has several plans?** It is the lowest price per month ("from" price in the store). The annual plan is converted to its monthly equivalent by the store itself. Use `rentalPlans` for the exact price of each plan. `price: 0` only appears when the store prints "Free" (or a price of zero); an unreadable price is `null`.

**Does it collect personal data?** It does not read reviews, reviewer names, support contacts or partner pages, and e-mail addresses are removed from the text fields. It does save the producer name exactly as the store prints it. That is usually a company, but a sole trader can be listed under their own name, which is then personal data of that person. Check the rules that apply to you (for example GDPR) before you store or share it.

**Is it polite to the store?** About one request per second, retries with back-off, and the store's `robots.txt` is read first and obeyed. The store reports how many requests it still allows; the actor pauses when that number gets low. On 24 October 2026 the store's `robots.txt` allowed all pages and the shopware AG terms (GTC) contained no clause about automated access to public pages that we could find. Please check the terms and the laws that apply to you before you reuse the data.

### Pricing

Pay per result — see the Pricing tab.

Each saved extension row is one result. Source rows and status rows are free. The run stops when it reaches the maximum cost per run that you set; when no result fits the remaining budget, it makes no robots, listing or extension requests. On graceful abort it saves `RUN_SUMMARY` and a `STATE` progress snapshot with saved extension codes, the current source and counters before shutdown. This snapshot does not automatically resume another run.

### Support and disclaimers

Questions and feature requests belong on the **Issues** tab of this Actor's page on Apify. This Actor is an independent tool and is not affiliated with Shopware AG or the producers of the extensions. It reads only what the store publishes on its public pages; how you may use that data depends on the store's terms and the applicable law.

# Actor input Schema

## `searchTerms` (type: `array`):

Words to look for in the Shopware Store, for example "seo" or "paypal". Each term is run through the store's own search (24 extensions per page, best match first), up to "Max listing pages" pages per term.

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

Optional. English store URLs on store.shopware.com/en/: a category or listing such as https://store.shopware.com/en/extensions/integration/legal-security/ or https://store.shopware.com/en/search?search=theme, or one extension page such as https://store.shopware.com/en/swag588949310744f/paypal-for-shopware-6.html.

## `shopwareVersions` (type: `array`):

Optional. Keep only extensions whose compatibility range contains at least one of these versions, for example 6.6 (any 6.6.x.y) or 6.7.2.0. The range is read from each extension page, so every candidate costs one extra request. Extensions whose page gives no version range are left out and counted in the source row.

## `maxItems` (type: `integer`):

Stop after this many extension rows in total. 0 = no limit (the pages limit below still applies).

## `maxListingPages` (type: `integer`):

Listing pages read per search term or listing URL. Each page holds 24 extensions, so 5 pages scan 120 extensions. The source row shows whether the whole listing was read.

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

Adds rental plans, compatible versions, last update, version, languages, downloads and category (one extra request per extension, about one per second). Turn off for a fast list of 24 extensions per request with name, producer, price, rating and short description. A Shopware version filter always reads the extension pages.

## `includeSourceInfo` (type: `boolean`):

One free row per search term, listing or extension URL: pages read, entries scanned, extensions skipped by the version filter, extensions saved, and whether the whole listing was read.

## Actor input object example

```json
{
  "searchTerms": [
    "seo"
  ],
  "shopwareVersions": [
    "6.7"
  ],
  "maxItems": 50,
  "maxListingPages": 5,
  "includeDetails": true,
  "includeSourceInfo": true
}
```

# Actor output Schema

## `extensions` (type: `string`):

No description

## `allFields` (type: `string`):

No description

## `summary` (type: `string`):

No description

# 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 = {
    "searchTerms": [
        "seo"
    ],
    "shopwareVersions": [
        "6.7"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("atesen-software/shopware-store-extensions-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 = {
    "searchTerms": ["seo"],
    "shopwareVersions": ["6.7"],
}

# Run the Actor and wait for it to finish
run = client.actor("atesen-software/shopware-store-extensions-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 '{
  "searchTerms": [
    "seo"
  ],
  "shopwareVersions": [
    "6.7"
  ]
}' |
apify call atesen-software/shopware-store-extensions-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,atesen-software/shopware-store-extensions-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/iYDlcwLDSupxy8O0h/builds/D9zI8QsxM4EXOADG8/openapi.json
