# Digitec Galaxus Scraper - Products, Prices & Specs (CH/DE) (`abotapi/galaxus-marketplace-scraper`) Actor

Scrape Digitec Galaxus, Switzerland's largest online retailer: products with local prices, discounts, ratings, stock state and full specification tables across the galaxus.ch, galaxus.de and digitec.ch storefronts. Search keywords or paste links, and monitor price changes with recurring updates.

- **URL**: https://apify.com/abotapi/galaxus-marketplace-scraper.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Features:** Limited permissions
- **Stats:** 7 total users, 4 monthly users, 87.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 1,000 product 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/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

## Digitec Galaxus Scraper: Products, Prices & Specs (CH/DE)

Digitec Galaxus Scraper turns the Galaxus Switzerland, Galaxus Germany and Digitec Switzerland storefronts into a clean product data feed. Search by keyword or paste your own product and category links, get local prices, currency, discounts, ratings, availability and promotion info on every row, and switch on a detail read for the full description, specification table, warranty and gallery. Export to JSON, CSV or Excel, or pull the results straight into your app through the API.

### Why This Scraper?

- **Three storefronts, one actor.** Galaxus Switzerland, Galaxus Germany and Digitec Switzerland, each with its own currency, covered by the same run.
- **Two ways to collect.** Keyword search walks a storefront's catalogue; your own links read exact product pages or walk whole category listings.
- **Category-aware search.** A keyword the store maps to a whole category is walked as that category, exactly what a shopper browsing the site would see.
- **Detail read on demand.** Switch on a per-product read for description, summary bullets, full specification table, warranty, gallery images, data sheet link and test report grade, billed only for the products you enrich.
- **Filter and sort like the storefront.** Price range and six sort orders (relevance, newest, price, rating, availability) are applied by the store itself, in both modes. The one exception is a toplist ranking page (and a brand hub that lists no product type): its rows are the page's own ranking, so the price range is applied to the ranked rows and the order stays the ranking.
- **Built for monitoring.** Recurring updates return only new and changed products on repeat runs, and a run that could not read anything fails loudly instead of returning an empty dataset.

### Use Cases

- **Price monitoring and repricing:** track prices, discounts and promotions across CH and DE storefronts to react to competitor moves.
- **Stock and availability alerts:** watch specific products or categories for restocks and availability changes with recurring updates.
- **Product research and comparison:** pull full specification tables and ratings to compare laptops, phones and other electronics before buying.
- **Catalogue and assortment analysis:** collect a whole category with sort and price filters to study assortment depth and pricing bands.
- **Content and marketplace feeds:** feed product data, images and specification tables into your own site, app or price comparison tool.

### Data You Get

> Sample shape: values are illustrative placeholders, not from a live record.

| Field | Example |
| --- | --- |
| `recordType` | `"product"` |
| `id` / `productId` | `"100000001"` / `100000001` |
| `name` | `"Sample Product 000000000"` |
| `brand` | `"Sample Brand"` |
| `productTypeName` / `productTypeId` | `"Notebooks"` / `6` |
| `url` | Galaxus or Digitec link to the product |
| `imageUrl` | Product image link |
| `currency` / `price` | `"CHF"` / `499.00` |
| `priceExclVat` | `461.61` |
| `oldPrice` / `discountPercent` | `649.50` / `23` |
| `ratingAverage` / `ratingCount` | `4.3` / `214` |
| `availability` / `stock` | availability class such as `"FULL"` / stock count and status (when reported) |
| `soldCount` / `canAddToCart` | `340` / `true` |
| `labels` / `promotionType` | `["DISCOUNT"]` / `"PROMOTION"` |
| `nameFull` / `category` | `"Sample Brand Sample Product 000000000"` / `"Notebooks"` |
| `inStock` / `energyRating` | `true` (null when the list data does not say) / energy class when the store reports one, otherwise null |
| `description` / `summary` | full text and bullet points (detail read only) |
| `keySpecifications` / `specifications` | key facts, then the full spec table, grouped by section (detail read only) |
| `warranty` / `returnPolicy` | `"24 Months Warranty (Bring-in)"` / return terms (detail read only) |
| `imageUrls` / `dataSheetUrl` | gallery images / manufacturer data sheet link (detail read only) |
| `testReportCount` / `testReportGrade` | `3` / `5.4` (detail read only) |
| `market` / `sourceType` / `sourceId` | `"CH"` / `"search"` / `"laptop"` |
| `scrapedAt` | `"2026-09-30T08:00:00Z"` |
| `changeType` / `changedFields` / `firstSeenAt` / `lastSeenAt` | recurring updates only, for example `"UPDATED"` / `["price"]` / first and last seen timestamps |

The Output tab offers three views: Results (all columns), Product details (description, specifications, warranty, test reports) and Changes (recurring-update rows). Each run also saves an `OUTPUT` summary in the key-value store with row counts per record kind and change type, sources read, failed and unsupported, and whether the item cap was reached.

### How to Use

1. Pick a **mode**: keyword search on one storefront, or your own product and category links.
2. Choose a **storefront**, then add one or more **search terms**, or paste product or category URLs from that storefront.
3. Turn on **Read product detail pages** if you need description and specifications, set **Max records** and **Max pages per source**, then click **Start**.
4. Download the dataset as JSON, CSV or Excel, or read it through the API.

**Keyword search, cheapest first:**

```json
{
  "mode": "search",
  "market": "galaxus-ch",
  "searchTerms": ["laptop"],
  "sortBy": "lowest-price",
  "maxItems": 20
}
```

**Walk a whole category from your own link:**

```json
{
  "mode": "urls",
  "urls": ["https://www.galaxus.ch/en/s1/producttype/notebooks-6"],
  "maxItems": 50
}
```

#### Links mode: supported link shapes

Each link is read on its own storefront (galaxus.ch, galaxus.de, digitec.ch), whatever the `market` field says. If you leave the `urls` field untouched in links mode, the actor scrapes one example of each shape below, so cap the run with `maxItems`. Search mode never reads the `urls` field when it holds that untouched example list, and setting only `categoryUrl` or `categorySlug` reads just that one category, never the examples.

| Link shape | Example | Behaviour |
| --- | --- | --- |
| Keyword search | `https://www.galaxus.ch/en/search?q=laptop`, `https://www.galaxus.ch/en/s1/search?q=logitech+mx+master+3s` | Walked as a keyword search (any locale, with or without the `/s1/` segment, bare domain accepted) |
| Product type category | `https://www.galaxus.ch/en/s1/producttype/notebooks-6` | Forward walk of the list |
| Category on another storefront | `https://www.galaxus.de/de/s1/producttype/notebooks-6`, `https://www.digitec.ch/en/s1/producttype/notebooks-6` | Walked on that storefront |
| Brand, filter or subtype inside a product type | `.../producttype/notebooks-6/brand/lenovo-5`, `.../producttype/notebooks-6/filter/operating-system-windows-35549`, `.../producttype/notebooks-6/subtype/notebook-type-gaming-laptop-14` | Walked with that one brand / attribute filter applied, so the count matches the filtered list the site shows |
| Tag / area page | `https://www.galaxus.ch/en/s1/tag/audio-591` | Forward walk |
| Sector page | `https://www.galaxus.ch/en/s1/sector/it-multimedia-1`, `https://www.galaxus.ch/en/s2/sector/home-kitchen-2` | Forward walk of the whole sector |
| Promotion, sale or second-hand | `https://www.galaxus.ch/en/s1/promotion/producttype/notebooks-6`, `https://www.galaxus.ch/en/s1/sale/producttype/notebooks-6`, `https://www.galaxus.ch/en/s1/secondhand/producttype/notebooks-6` | Forward walk of that offer list only |
| Promotion / sale overview | `https://www.galaxus.ch/en/s1/promotion`, `https://www.galaxus.ch/en/s1/sale` | Forward walk of everything on offer / on sale |
| Category with parameters | `https://www.galaxus.ch/en/s1/producttype/notebooks-6?sorting=PRICE_ASC` or `...notebooks-6?pf=price_min_500_max_1000` | `sortOrder` (or `sorting`), `priceFrom` / `priceTo` and the site's `pf=price_min_500_max_1000` in the link override the run's sort and price fields for that link |
| Single product | `https://www.galaxus.ch/en/s1/product/<slug>-<id>` or `.../product/<id>` | One product read through the detail data |
| Toplist ranking | `https://www.galaxus.ch/en/s1/producttype/toplist/relevance/notebooks-6` | The ranked products the page itself shows (about ten rows per ranking page). Min price (optional) / Max price (optional) are applied to those rows (out-of-range rows are dropped, not delivered); Ordering is not applied, the order is the ranking |
| Brand hub | `https://www.galaxus.ch/en/brand/benq-2` | The brand's own products inside each product type the hub lists, walked one after another with the brand filter applied (falls back to the hub's top-rated products when it lists no product type; that fallback keeps its ranking order and has Min price (optional) / Max price (optional) applied to its rows) |
| Page number in a link | `...notebooks-6?page=2` | The site itself ignores `page=` and re-serves the first rows, so the link is the same list as the plain category link and the whole list is walked from the start (use Max Items to bound it) |
| Any other page (for example a buying guide or blog page) | `https://www.galaxus.ch/en/s1/producttype/notebooks-6/buying-guide` | Not a product list: skipped with a warning naming the link. If every link is of this kind the run fails with a message naming the link and the supported shapes; it never reports a connection problem |

**Search with full product detail:**

```json
{
  "mode": "search",
  "market": "galaxus-de",
  "searchTerms": ["kaffeemaschine"],
  "fetchDetails": true,
  "maxItems": 10
}
```

**Recurring updates, only what changed:**

```json
{
  "mode": "search",
  "market": "digitec-ch",
  "searchTerms": ["smartphone"],
  "incrementalMode": true,
  "emitExpired": true,
  "maxItems": 0
}
```

#### Run it from your code

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/galaxus-marketplace-scraper").call(run_input={"mode": "search", "market": "galaxus-ch", "searchTerms": ["laptop"], "maxItems": 20})
for product in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(product["name"], product["price"], product["currency"])
```

JavaScript:

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/galaxus-marketplace-scraper').call({ mode: 'search', market: 'galaxus-ch', searchTerms: ['laptop'], maxItems: 20 });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the **Integrations** tab.

#### How Max records and Max pages shape a run

**Max records** is the single limit that stops a run; it defaults to 1000 and accepts up to 1000000; `0` still means collect until the catalogue or your links run out. When a run has several search terms or links, the record cap is split across them so each gets a fair share; a source that is capped before it finishes is marked as not having reached its natural end. **Max pages per source** is a guardrail on how many reads any one search or category walk may spend, independent of the record cap.

#### Resume and recurring updates

- **Continue a previous run** (`resumeFromRunId`) finishes one interrupted run: paste its run or dataset id and records it already returned are skipped, so a large collection does not pay for the same rows twice.
- **Recurring updates** (`incrementalMode`) is for running the same setup again and again, for example daily. Each record is classified `NEW`, `UPDATED` (with `changedFields`), `UNCHANGED` (suppressed and not billed unless `emitUnchanged` is on), `REAPPEARED` or `EXPIRED` (only after a run that covered its whole setup, and only with `emitExpired`). `stateKey` names or shares the stored memory; leave it empty and the memory is keyed on the run setup automatically. With recurring updates off, output is exactly as before.
- **What is compared and what is not.** Every output column is compared except `scrapedAt`, `position`, the `source*` columns, `promotionRemainingDays` and `soldCount`: those change on their own every day, stay in your output, and never decide `UPDATED`. A change in price, old price, discount, rating, review count, availability, stock, labels, promotion type or detail data makes a record `UPDATED`, and `changedFields` names what moved.
- **Ignore fields when detecting changes** (`ignoreFieldsForChanges`) adds your own column names to that excluded list (dotted paths such as `specifications.value` reach into nested lists). Ignored columns stay in the output. Changing this setting keeps your stored memory: records are re-compared under the new list, so nothing is billed again as `NEW`.
- **Change scope** (`changeScope`, default `all`): `priceAndStock` compares only price, price excluding VAT, old price, discount, currency, availability, stock and the can-add-to-cart flag, so name, image, label or description changes never create an `UPDATED` row. Switching it on or off keeps your stored memory and does not bill the catalogue again as `NEW`.
- **Slim updates** (`compactUpdates`, default off): `UPDATED` rows carry only identifiers, current price and stock and `priceChanges` (old and new per moved field); `EXPIRED` rows carry identifiers and the last price and stock; `NEW` rows stay full. A slim row has no detail data, so it never triggers the per-product detail surcharge.
- **Missed scans before EXPIRED** (`expireAfterMissedScans`, default 1): with `emitExpired`, a record is reported gone only after it was absent from that many complete scans in a row. `EXPIRED` means "no longer found in the listing"; without a product-page check a listing drop and a delisting look the same, so use the stock fields for availability. A run stopped by Max records, Max pages, a failed source, or a continued run never reports records as gone.
- Changing the ignore list or the change scope under an automatic state key starts a fresh baseline (the first run returns everything as `NEW`); set a `stateKey` to keep one baseline.

### Send results into your apps (MCP connectors)

Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step **after** the scrape: the Apify dataset is never changed.

**What gets written to the connector:** a condensed, human-readable **summary** of each product, not the full JSON. Each item becomes one entry with a **title** and its key fields flattened to plain text. The **complete record always stays in the Apify dataset**.

1. Authorize a connector once under **Apify, Settings, Integrations** (Notion, Linear, Airtable, or Apify).
2. Select it in the **"Pipe results into your apps"** input field. If the picker is empty, you have not authorized a connector yet.
3. For **Notion**, also set `notionParentPageUrl` to the page where items should be created.

The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.

### Input Parameters

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `mode` | string | `search` | `search` (keyword search) or `urls` (your own product and category links). |
| `market` | string | `galaxus-ch` | Storefront: `galaxus-ch`, `galaxus-de` or `digitec-ch`. In links mode, set it to the storefront your links are on. |
| `searchTerms` | array | `["laptop"]` | One entry per search; each search is walked forward and all searches share the record cap. Search mode only. |
| `sortBy` | string | `relevance` | Ordering for each source: `relevance`, `newest`, `lowest-price`, `highest-price`, `rating` or `availability`. Ranking pages keep their own order (the page's ranking wins). |
| `minPrice` | integer | (none) | Only return products at or above this price, in the storefront's currency. On ranking pages (toplists, brand-hub fallbacks) the price range is applied to the page's own rows instead. |
| `maxPrice` | integer | (none) | Only return products at or below this price, in the storefront's currency. On ranking pages (toplists, brand-hub fallbacks) the price range is applied to the page's own rows instead. |
| `includeOutOfStock` | boolean | `true` | Off drops products whose list data says they cannot be bought. Products with unknown stock are kept. Dropped products are still counted as present, so recurring updates never mark them `EXPIRED`. Turning this off starts its own stored memory when `stateKey` is empty. |
| `categoryUrl` | string | (none) | Read one category without search terms: a category link. Used when no search terms are given. |
| `categorySlug` | string | (none) | Same, as a product-type slug such as `notebooks-6`. |
| `urls` | array | one example of each link shape (table below) | Search, category and product links to read. Links mode only. |
| `fetchDetails` | boolean | `false` | Read each product's own page and add description, summary, specifications, warranty, gallery and data sheet. Billed as a per-product surcharge. |
| `maxItems` | integer | `1000` (prefilled `20`) | Stop after this many records across the whole run; maximum `1000000`; `0` means no limit. A run that leaves `maxItems` out is capped at 1000 records. |
| `maxPages` | integer | `0` | Guardrail on reads per source; `0` goes as deep as the source serves. |
| `resumeFromRunId` | string | (none) | Continue one interrupted run: paste its run or dataset id. |
| `incrementalMode` | boolean | `false` | Turn on for recurring runs that should return only new and changed records. |
| `stateKey` | string | (none) | Name or share a recurring-updates memory. Recurring updates only. |
| `emitUnchanged` | boolean | `false` | Also return (and bill) records that did not change. Recurring updates only. |
| `emitExpired` | boolean | `false` | Also return (and bill) records that are gone. Recurring updates only. |
| `changeScope` | string | `all` | `all` or `priceAndStock`. Recurring updates only. |
| `compactUpdates` | boolean | `false` | Slim `UPDATED` and `EXPIRED` rows. Recurring updates only. |
| `expireAfterMissedScans` | integer | `1` | Complete scans a record must miss before `EXPIRED`. Recurring updates only. |
| `ignoreFieldsForChanges` | array | (none) | Columns that never make a record `UPDATED`. Recurring updates only. |
| `mcpConnectors` | array | (none) | Optional: send a summary of each record to apps you authorized under Integrations. |
| `notionParentPageUrl` | string | (none) | Notion connector only: page under which item pages are created. |
| `maxNotifyListings` | integer | `50` | Cap on items written to each connector per run. Does not affect the dataset. |
| `proxyConfiguration` | object | Apify Proxy | Connection used for every request. The default works; you can also bring your own connection links. |

### Output Example

> Sample shape: values are illustrative placeholders, not from a live record.

```json
{
  "recordType": "product",
  "id": "100000001",
  "productId": 100000001,
  "name": "Sample Product 000000000",
  "brand": "Sample Brand",
  "productTypeName": "Notebooks",
  "productTypeId": 6,
  "url": "https://www.galaxus.ch/en/s1/product/sample-product-15-inch-100000001",
  "imageUrl": "https://www.galaxus.ch/productimages/sample",
  "currency": "CHF",
  "price": 499.00,
  "priceExclVat": 461.61,
  "oldPrice": 649.50,
  "discountPercent": 23,
  "ratingAverage": 4.3,
  "ratingCount": 214,
  "availability": "FULL",
  "stock": { "stockCount": 12, "stockStatus": "IN_STOCK", "expectedDelivery": null },
  "soldCount": 340,
  "labels": ["DISCOUNT"],
  "promotionType": "PROMOTION",
  "promotionRemainingDays": 3,
  "canAddToCart": true,
  "market": "CH",
  "marketHost": "www.galaxus.ch",
  "sourceType": "search",
  "sourceId": "laptop",
  "sourceUrl": null,
  "position": 1,
  "scrapedAt": "2026-09-30T08:00:00Z"
}
```

### Plan Requirement

An Apify plan with proxy access is required: the storefront refuses plain non-browser connections, and the actor reads it through your Apify Proxy (or your own proxy URLs). The default Connection & proxy setting is the right starting point. Listing, search and category reads are served on the default Apify Proxy datacenter tier; residential is used only as an automatic escalation when a connection is refused, so the actor continues on a backup connection and logs this notice:

> The selected connection is unavailable to this run. Apify free plans do not include residential proxies. Continuing on a backup connection; some pages may still be unavailable.

When a read is served that way the log says "Served over the backup connection (the default connection was unavailable)." If nothing at all could be read, the run fails with one of these messages instead of returning an empty dataset:

- **Proxy refused for the account:** "The proxy connection was refused for this account, so no page could be read. Your Apify plan does not include proxy access; a paid plan is required." Check your plan, or your own proxy credentials if you entered proxy URLs.
- **Residential unavailable:** "No results: residential proxies are unavailable on this run (Apify free plans do not include them), and the backup connection could not load the requested Galaxus pages."
- **Requests failed:** "Could not load any results page (the requests failed), so nothing was collected. This is a connection problem, not an empty search."
- **Links that are not product lists:** "None of the pasted links could be read as a product list." followed by the link and the supported link shapes. This is an input problem, not a connection problem.

Product pages themselves are not served to plain requests, so product details are read through the storefront's data service rather than the page. Output text (names, categories, URLs) is English whatever locale prefix such as `/de/` or `/fr/` the link carries; a pasted link selects the storefront and its currency, not the text language, and there is no separate language input.

### FAQ

#### How much does it cost?

You pay a run-start event, a charge per record returned (unchanged records in recurring updates are not billed unless you ask for them), and a per-product detail surcharge only when you switch on the detail read. Reviews are not collected, so there is no review charge. The **Pricing** tab shows the current rates. Use **Max records** to cap the cost of any run.

#### Is it legal to scrape Digitec Galaxus?

This actor collects only publicly visible catalogue pages for your own analysis. You are responsible for how you use it: follow the store's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. It is an independent tool with no affiliation with the store operator.

#### Can I get only new or changed products on a schedule?

Yes. Schedule the actor from the **Schedules** tab and turn on **Recurring updates**. Each run then returns only new and updated products, and unchanged ones are not billed unless you ask for them.

#### Why does a search sometimes return a whole category instead of a short list?

When the store itself maps a search term to one of its own categories, the actor follows that redirect and walks the category, which is exactly what a shopper typing the same term would see. This can return more products than a narrow keyword match would suggest.

#### Why did my run fail instead of returning an empty dataset?

If the store refuses every request, the run stops with a clear message so "no products for this search" is never confused with "nothing could be read". Run it again in a few minutes. If only some searches or links could be read, you still get what was found.

#### Can I use it with AI agents or MCP?

Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.

### 🔗 More scrapers you might like

Pair this actor with these related scrapers from the same team:

<table>
<tr><td>🧩 <a href="https://apify.com/abotapi/vidaxl-com-scraper"><b>VidaXL Scraper</b></a><br>Scrape the vidaXL storefronts by keyword or URL across 6 European markets. Every row...</td><td>🧩 <a href="https://apify.com/abotapi/jumia-marketplace-scraper"><b>Jumia Marketplace Scraper</b></a><br>Scrape Jumia, Africa's largest marketplace: products with local prices, discounts...</td></tr>
<tr><td>🧩 <a href="https://apify.com/abotapi/falabella-marketplace-scraper"><b>Falabella Scraper</b></a><br>Scrape Falabella, Latin America's leading retail marketplace: products with local prices...</td><td>🛒 <a href="https://apify.com/abotapi/americanas-com-br-scraper"><b>Americanas Brazil</b></a><br>Scrape Americanas Brazil (americanas.com.br) by keyword, department or pasted link...</td></tr>
<tr><td>🛒 <a href="https://apify.com/abotapi/shein-product-scraper"><b>SHEIN Scraper</b></a><br>Scrape SHEIN product listings by keyword or from any category, sale or search link...</td><td>🧩 <a href="https://apify.com/abotapi/ebay-com-scraper"><b>eBay Scraper</b></a><br>Scrape eBay by keyword, category, seller or pasted link across 16 country storefronts...</td></tr>
</table>

👉 [Browse all abotapi scrapers](https://apify.com/abotapi)

### 💬 Support

- 🐞 **Found a bug or a missing field?** Open a ticket on the [Issues tab](https://apify.com/abotapi/galaxus-marketplace-scraper/issues/open). We usually reply within hours.
- 🛠️ **Need another site, extra fields or a private build?** Email <contact@abotapi.com>.
- ⭐ **Enjoying it?** A quick review on the actor page helps other users find it.

# Actor input Schema

## `mode` (type: `string`):

Where to collect from: a keyword search on one storefront, or your own product and category links.

## `market` (type: `string`):

Which storefront to search. Each storefront is its own catalogue with its own currency (Swiss Francs on the Swiss shops, euros on the German shop).

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

Only read when mode = keyword search. One entry per search; each search is walked forward, and all searches share the record cap.

## `sortBy` (type: `string`):

Order in which products are returned for each source. Ranking pages (toplist links) keep their own ranking order.

## `minPrice` (type: `integer`):

Only return products at or above this price, in the selected storefront's currency. Applied by the store in both modes, except ranking pages (toplist links), whose price range is applied to the ranked rows; price ranges on very large categories are server-side counts, so a wide range narrows strongly.

## `maxPrice` (type: `integer`):

Only return products at or below this price, in the selected storefront's currency. Applied by the store in both modes, except ranking pages (toplist links), whose price range is applied to the ranked rows.

## `includeOutOfStock` (type: `boolean`):

Off drops products whose list data says they cannot be bought; products with unknown stock are always kept.

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

Only read when mode = my own links. Paste search links (/search?q=), category links (product type, tag, sector, promotion or sale pages, with sortOrder / priceFrom / priceTo in the link honoured) for a forward walk, or single product page links for one enriched product each. Each link is read on its own storefront (galaxus.ch, galaxus.de, digitec.ch). Left untouched, the field scrapes one example of each link shape.

## `categoryUrl` (type: `string`):

One category page link, walked like a pasted link. When set and no search terms are given, the run reads this category instead of searching.

## `categorySlug` (type: `string`):

A product-type slug such as notebooks-6, read on the selected storefront. Ignored when a category link is set.

## `fetchDetails` (type: `boolean`):

Read each product's own page data and add the description, summary bullets, full specification table, key specifications, warranty, gallery images, data-sheet link and test-report grade to the record. Off by default: a run without it is cheaper and still carries prices, discounts, ratings, availability and promotion info.

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

Stop after this many records across the whole run (default 1000, at most 1000000; 0 = no limit and the walk then ends when the catalogue runs out).

## `maxPages` (type: `integer`):

Guardrail bound on how many reads any single search or category walk may spend. Leave 0 to go as deep as the source serves, with the record cap above as the only real limit.

## `proxyConfiguration` (type: `object`):

Connection used for every request. The storefront answers ordinary connections, so the plain default works; you can also paste your own connection links.

## `resumeFromRunId` (type: `string`):

Paste the run id (or dataset id) of an earlier run of this Actor to continue it. Records that run already returned are skipped, so an interrupted large collection can finish without paying for the same rows twice. Leave empty for a normal run.

## `incrementalMode` (type: `boolean`):

Turn this on for daily or weekly monitoring. The first run returns everything as NEW. Later runs return only NEW, UPDATED and REAPPEARED records, each labelled in a changeType column. What is compared: every output column except the ones excluded below, so a change in price, old price, discount, rating, review count, availability, stock, labels, promotion type or detail data makes a record UPDATED, and changedFields names what moved. What is excluded: scrapedAt, position, the source columns, promotionRemainingDays and soldCount (they change on their own every day); they stay in the output but never decide UPDATED. Add more with the ignore-fields input below, or compare price and stock only with Change scope. Leave off for a normal one-off run.

## `stateKey` (type: `string`):

Optional. Name this monitoring campaign to keep its memory stable, or to deliberately share one memory across differently configured runs. Leave empty and the memory is keyed on the run setup automatically.

## `emitUnchanged` (type: `boolean`):

Off by default. Turn on to also return records that have not changed since the last run, labelled UNCHANGED. This returns, and bills, rows you already have.

## `emitExpired` (type: `boolean`):

Off by default. Turn on to also return records that were present before and are no longer found, labelled EXPIRED. Only produced when a run covered its whole setup, so a capped or continued run never reports records as gone. This returns, and bills, extra rows.

## `changeScope` (type: `string`):

All (default) compares every column except the excluded ones. Price and stock only compares price, price without VAT, old price, discount, currency, availability, stock and the can-add-to-cart flag, so a changed name, image, label, rating or description never creates a billable UPDATED row. Switching scope under an automatic state key starts a fresh baseline (the first run returns everything as NEW); set a State key to keep one baseline.

## `compactUpdates` (type: `boolean`):

Off by default. When on, UPDATED rows carry only the identifiers, the current price and stock and priceChanges (old and new per moved field), and EXPIRED rows only the identifiers and last price and stock. NEW rows stay full. A slim row does not carry detail data, so it does not trigger the per-product detail surcharge.

## `expireAfterMissedScans` (type: `integer`):

With Also return records that are gone on, a record is reported EXPIRED only after it was missing from this many complete scans in a row (1 = the first complete scan that misses it). EXPIRED means the product was not found in the listing; without a detail check a listing drop and a delisting look the same, so read the stock fields for availability.

## `ignoreFieldsForChanges` (type: `array`):

Column names that must never make a record UPDATED, for example labels or ratingCount. Use a dotted path such as specifications.value for a key inside a nested list. The ignored columns still appear in the output. Changing this under an automatic state key starts a fresh baseline; set a State key to keep one.

## `mcpConnectors` (type: `array`):

Optionally send results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize one under Apify, Settings, API & Integrations, then select it here. Notion gets a rich page-per-item export; other connectors get a best-effort write or digest. Leave empty to skip; never changes the dataset output.

## `notionParentPageUrl` (type: `string`):

URL or id of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors.

## `maxNotifyListings` (type: `integer`):

Cap on items written to each connector per run. Does not affect the dataset.

## Actor input object example

```json
{
  "mode": "search",
  "market": "galaxus-ch",
  "searchTerms": [
    "laptop"
  ],
  "sortBy": "relevance",
  "includeOutOfStock": true,
  "urls": [
    "https://www.galaxus.ch/en/search?q=laptop",
    "https://www.galaxus.ch/de/search?q=laptop",
    "https://galaxus.ch/en/search?q=usb+cable",
    "https://www.galaxus.ch/en/s1/producttype/notebooks-6",
    "https://www.galaxus.de/de/s1/producttype/notebooks-6",
    "https://www.digitec.ch/en/s1/producttype/notebooks-6",
    "https://www.galaxus.ch/en/s1/tag/audio-591",
    "https://www.galaxus.ch/en/s2/sector/home-kitchen-2",
    "https://www.galaxus.ch/en/s1/promotion/producttype/notebooks-6",
    "https://www.galaxus.ch/en/s1/sale/producttype/notebooks-6",
    "https://www.galaxus.ch/en/s1/producttype/notebooks-6?sorting=PRICE_ASC",
    "https://www.galaxus.ch/en/s1/producttype/notebooks-6?pf=price_min_500_max_1000",
    "https://www.galaxus.ch/en/s1/product/logitech-mx-master-3s-wireless-mouse-61318913",
    "https://www.digitec.ch/en/s1/product/61318913",
    "https://www.galaxus.ch/en/s1/search?q=logitech+mx+master+3s",
    "https://www.galaxus.ch/en/s1/producttype/notebooks-6/brand/lenovo-5",
    "https://www.galaxus.ch/en/s1/producttype/notebooks-6/filter/operating-system-windows-35549",
    "https://www.galaxus.ch/en/s1/producttype/notebooks-6/subtype/notebook-type-gaming-laptop-14",
    "https://www.galaxus.ch/en/s1/sector/it-multimedia-1",
    "https://www.galaxus.ch/en/s1/promotion",
    "https://www.galaxus.ch/en/s1/sale",
    "https://www.galaxus.ch/en/s1/secondhand/producttype/notebooks-6",
    "https://www.galaxus.ch/en/s1/producttype/toplist/relevance/notebooks-6",
    "https://www.galaxus.ch/en/brand/benq-2"
  ],
  "fetchDetails": false,
  "maxItems": 20,
  "maxPages": 0,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "changeScope": "all",
  "compactUpdates": false,
  "expireAfterMissedScans": 1,
  "maxNotifyListings": 50
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

## `detail` (type: `string`):

No description

## `changes` (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 = {
    "mode": "search",
    "market": "galaxus-ch",
    "searchTerms": [
        "laptop"
    ],
    "sortBy": "relevance",
    "urls": [
        "https://www.galaxus.ch/en/search?q=laptop",
        "https://www.galaxus.ch/de/search?q=laptop",
        "https://galaxus.ch/en/search?q=usb+cable",
        "https://www.galaxus.ch/en/s1/producttype/notebooks-6",
        "https://www.galaxus.de/de/s1/producttype/notebooks-6",
        "https://www.digitec.ch/en/s1/producttype/notebooks-6",
        "https://www.galaxus.ch/en/s1/tag/audio-591",
        "https://www.galaxus.ch/en/s2/sector/home-kitchen-2",
        "https://www.galaxus.ch/en/s1/promotion/producttype/notebooks-6",
        "https://www.galaxus.ch/en/s1/sale/producttype/notebooks-6",
        "https://www.galaxus.ch/en/s1/producttype/notebooks-6?sorting=PRICE_ASC",
        "https://www.galaxus.ch/en/s1/producttype/notebooks-6?pf=price_min_500_max_1000",
        "https://www.galaxus.ch/en/s1/product/logitech-mx-master-3s-wireless-mouse-61318913",
        "https://www.digitec.ch/en/s1/product/61318913",
        "https://www.galaxus.ch/en/s1/search?q=logitech+mx+master+3s",
        "https://www.galaxus.ch/en/s1/producttype/notebooks-6/brand/lenovo-5",
        "https://www.galaxus.ch/en/s1/producttype/notebooks-6/filter/operating-system-windows-35549",
        "https://www.galaxus.ch/en/s1/producttype/notebooks-6/subtype/notebook-type-gaming-laptop-14",
        "https://www.galaxus.ch/en/s1/sector/it-multimedia-1",
        "https://www.galaxus.ch/en/s1/promotion",
        "https://www.galaxus.ch/en/s1/sale",
        "https://www.galaxus.ch/en/s1/secondhand/producttype/notebooks-6",
        "https://www.galaxus.ch/en/s1/producttype/toplist/relevance/notebooks-6",
        "https://www.galaxus.ch/en/brand/benq-2"
    ],
    "fetchDetails": false,
    "maxItems": 20,
    "maxPages": 0,
    "proxyConfiguration": {
        "useApifyProxy": true
    },
    "incrementalMode": false,
    "emitUnchanged": false,
    "emitExpired": false,
    "compactUpdates": false,
    "maxNotifyListings": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/galaxus-marketplace-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 = {
    "mode": "search",
    "market": "galaxus-ch",
    "searchTerms": ["laptop"],
    "sortBy": "relevance",
    "urls": [
        "https://www.galaxus.ch/en/search?q=laptop",
        "https://www.galaxus.ch/de/search?q=laptop",
        "https://galaxus.ch/en/search?q=usb+cable",
        "https://www.galaxus.ch/en/s1/producttype/notebooks-6",
        "https://www.galaxus.de/de/s1/producttype/notebooks-6",
        "https://www.digitec.ch/en/s1/producttype/notebooks-6",
        "https://www.galaxus.ch/en/s1/tag/audio-591",
        "https://www.galaxus.ch/en/s2/sector/home-kitchen-2",
        "https://www.galaxus.ch/en/s1/promotion/producttype/notebooks-6",
        "https://www.galaxus.ch/en/s1/sale/producttype/notebooks-6",
        "https://www.galaxus.ch/en/s1/producttype/notebooks-6?sorting=PRICE_ASC",
        "https://www.galaxus.ch/en/s1/producttype/notebooks-6?pf=price_min_500_max_1000",
        "https://www.galaxus.ch/en/s1/product/logitech-mx-master-3s-wireless-mouse-61318913",
        "https://www.digitec.ch/en/s1/product/61318913",
        "https://www.galaxus.ch/en/s1/search?q=logitech+mx+master+3s",
        "https://www.galaxus.ch/en/s1/producttype/notebooks-6/brand/lenovo-5",
        "https://www.galaxus.ch/en/s1/producttype/notebooks-6/filter/operating-system-windows-35549",
        "https://www.galaxus.ch/en/s1/producttype/notebooks-6/subtype/notebook-type-gaming-laptop-14",
        "https://www.galaxus.ch/en/s1/sector/it-multimedia-1",
        "https://www.galaxus.ch/en/s1/promotion",
        "https://www.galaxus.ch/en/s1/sale",
        "https://www.galaxus.ch/en/s1/secondhand/producttype/notebooks-6",
        "https://www.galaxus.ch/en/s1/producttype/toplist/relevance/notebooks-6",
        "https://www.galaxus.ch/en/brand/benq-2",
    ],
    "fetchDetails": False,
    "maxItems": 20,
    "maxPages": 0,
    "proxyConfiguration": { "useApifyProxy": True },
    "incrementalMode": False,
    "emitUnchanged": False,
    "emitExpired": False,
    "compactUpdates": False,
    "maxNotifyListings": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/galaxus-marketplace-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 '{
  "mode": "search",
  "market": "galaxus-ch",
  "searchTerms": [
    "laptop"
  ],
  "sortBy": "relevance",
  "urls": [
    "https://www.galaxus.ch/en/search?q=laptop",
    "https://www.galaxus.ch/de/search?q=laptop",
    "https://galaxus.ch/en/search?q=usb+cable",
    "https://www.galaxus.ch/en/s1/producttype/notebooks-6",
    "https://www.galaxus.de/de/s1/producttype/notebooks-6",
    "https://www.digitec.ch/en/s1/producttype/notebooks-6",
    "https://www.galaxus.ch/en/s1/tag/audio-591",
    "https://www.galaxus.ch/en/s2/sector/home-kitchen-2",
    "https://www.galaxus.ch/en/s1/promotion/producttype/notebooks-6",
    "https://www.galaxus.ch/en/s1/sale/producttype/notebooks-6",
    "https://www.galaxus.ch/en/s1/producttype/notebooks-6?sorting=PRICE_ASC",
    "https://www.galaxus.ch/en/s1/producttype/notebooks-6?pf=price_min_500_max_1000",
    "https://www.galaxus.ch/en/s1/product/logitech-mx-master-3s-wireless-mouse-61318913",
    "https://www.digitec.ch/en/s1/product/61318913",
    "https://www.galaxus.ch/en/s1/search?q=logitech+mx+master+3s",
    "https://www.galaxus.ch/en/s1/producttype/notebooks-6/brand/lenovo-5",
    "https://www.galaxus.ch/en/s1/producttype/notebooks-6/filter/operating-system-windows-35549",
    "https://www.galaxus.ch/en/s1/producttype/notebooks-6/subtype/notebook-type-gaming-laptop-14",
    "https://www.galaxus.ch/en/s1/sector/it-multimedia-1",
    "https://www.galaxus.ch/en/s1/promotion",
    "https://www.galaxus.ch/en/s1/sale",
    "https://www.galaxus.ch/en/s1/secondhand/producttype/notebooks-6",
    "https://www.galaxus.ch/en/s1/producttype/toplist/relevance/notebooks-6",
    "https://www.galaxus.ch/en/brand/benq-2"
  ],
  "fetchDetails": false,
  "maxItems": 20,
  "maxPages": 0,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "compactUpdates": false,
  "maxNotifyListings": 50
}' |
apify call abotapi/galaxus-marketplace-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,abotapi/galaxus-marketplace-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/kGeNVFhdlLu6GS2lp/builds/HpKY88iagYLcuA66v/openapi.json
