# Otto.de Product Scraper (`solidcode/otto-de-scraper`) Actor

\[💰 $1.2 / 1K] Scrape products from Otto.de, Germany's leading online marketplace: name, brand, price, compare-at price, discount, sale flags, rating, review count, availability, colors, images and sustainability badges. Search by keyword or paste Otto.de URLs, sort six ways, and skip sponsored ads

- **URL**: https://apify.com/solidcode/otto-de-scraper.md
- **Developed by:** [SolidCode](https://apify.com/solidcode) (community)
- **Categories:** E-commerce, Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Otto.de Product Scraper

Pull structured product data from Otto.de, one of Germany's largest online marketplaces — brands, EUR prices, compare-at prices, computed discounts, ratings, review counts, delivery availability, colour variants, images, and Otto's own sustainability badges. Search by keyword or paste any Otto.de search or category address. Built for pricing analysts, e-commerce teams, and market researchers who need a clean German marketplace dataset without babysitting a fragile in-house collector.

### Why This Scraper?

- **Six sort orders, including Biggest Discount** — Topseller, Price: Low to High, Price: High to Low, Biggest Discount, New Arrivals, and Best Rated. Sorting by Biggest Discount surfaced products at 72–84% off in live testing — a ready-made deal feed you cannot build from a plain keyword dump.
- **No result ceiling** — a single `shirt` search reaches all ~27,300 matching products, and collection runs to the true end of Otto's ranked list rather than stopping at an arbitrary page. Up to 50,000 products per run.
- **Sustainability badges on roughly 2 in 3 products** — Otto's own eco labels (for example "Verbesserte Rohstoffbeschaffung") arrive as readable German text, not internal codes. Around 80 of every 120 products carry at least one — a genuinely differentiating signal for German market research.
- **Discount percentage as a computed number, not a display badge** — instead of relying on Otto's on-tile "-14%" tag, we calculate the exact percentage off against the compare-at price or the RRP. It populates on roughly 3 in 4 products in live testing, and on effectively every result once you sort by Biggest Discount — a numeric `discountPercent` column you can actually sort, threshold, and filter on.
- **Ad-free by default, and labelled either way** — Otto mixes roughly 1 in 10 paid placements into its results. They are excluded by default and never charged for; turn them on and every row is still marked `organic` or `sponsored`, so you can measure ad share on purpose.
- **Price range narrowed by Otto itself** — a 10–300 EUR range is applied on Otto's side, so products outside your range are never collected and never charged for. Verified live: a 10–30 EUR range returns 10,21 € to 29,99 € and nothing else.
- **Category addresses resolve to Otto's real taxonomy** — `/damen/mode/shirts/` and `/herren/mode/jeans/` sit under internal categories the address slug never reveals, and this scraper resolves them exactly as Otto does. Any facets already applied in a pasted address, such as a price band, are kept intact.
- **26 typed fields per product** — including average rating, review count, delivery availability text, base colour plus every available colourway, and a `From price` flag that tells you when a price is a "starting at" figure rather than the exact one. German prices like `1.399,00 €` arrive as real numbers (`1399.0`).
- **German keywords, umlauts, and phrases all work** — `küchenmaschine` and `blaues hemd` return full result sets, so you can search the way German shoppers actually search.

### Use Cases

**Price Monitoring & Repricing**
- Track competitor prices across a product category on a daily schedule
- Detect discount events the moment Otto flags them, via the Biggest Discount sort
- Compare street price against RRP to measure real market positioning
- Feed EUR pricing into repricing engines for the DACH market

**Competitor & Brand Research**
- Measure a brand's shelf presence and average price point inside a category
- See which brands buy paid placement, and how often, by including sponsored results
- Benchmark your assortment against Otto's Topseller ranking

**Market Research**
- Size a German category by total product count before entering it
- Analyse rating and review-count distributions to find under-served segments
- Track new arrivals week over week to spot emerging products

**Sustainability & ESG Analysis**
- Quantify how much of a category carries Otto's eco labels
- Compare sustainability badge coverage across brands
- Build ESG-aware product shortlists for procurement

**Catalogue & Content Operations**
- Enrich internal catalogues with images, colourways, and delivery availability
- Build affiliate and comparison feeds with direct product links
- Populate merchandising dashboards with fresh German marketplace data

### Getting Started

#### Simple Keyword Search

The minimum input — one keyword:

```json
{
    "searchQueries": ["shirt"],
    "maxResults": 100
}
````

#### Deal Hunting — Biggest Discounts in a Price Band

Find the deepest reductions on coffee machines between 200 and 800 EUR:

```json
{
    "searchQueries": ["kaffeevollautomat"],
    "sortBy": "hoechste-reduzierung",
    "minPrice": 200,
    "maxPrice": 800,
    "maxResults": 500
}
```

#### Category and Search Addresses

Paste any Otto.de category or search page — both are collected exactly as Otto scopes them:

```json
{
    "startUrls": [
        "https://www.otto.de/damen/mode/shirts/",
        "https://www.otto.de/suche/shirt/"
    ],
    "sortBy": "neuheiten",
    "maxResults": 240
}
```

#### Full Sweep — Everything, Ads Included

German keywords plus a category, best-rated first, with paid placements kept for ad-share analysis:

```json
{
    "searchQueries": ["küchenmaschine", "blaues hemd"],
    "startUrls": ["https://www.otto.de/herren/mode/jeans/"],
    "sortBy": "bewertung",
    "minPrice": 10,
    "maxPrice": 300,
    "includeSponsored": true,
    "maxResults": 0
}
```

### Input Reference

#### What to Scrape

Provide search keywords, paste Otto.de addresses, or both — at least one is needed to get results.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `searchQueries` | string\[] | `["shirt"]` | Keywords to search on Otto.de, such as `"shirt"` or `"kaffeevollautomat"`. Each keyword runs its own search and the search is built for you — no need to create addresses. Umlauts and multi-word phrases are fully supported. |
| `startUrls` | string\[] | `[]` | Otto.de search or category page addresses, such as `https://www.otto.de/suche/shirt/` or `https://www.otto.de/damen/mode/shirts/`. Both page types are collected exactly as Otto scopes them, and any filters already in the pasted address (for example a price range) are kept. |

#### Filters

Otto applies the sort order and price range itself, so these also decide which products you get when you set a result limit.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `sortBy` | string | `"topseller"` | Order in which products are collected. One of `topseller` (Topseller), `preis-aufsteigend` (Price: Low to High), `preis-absteigend` (Price: High to Low), `hoechste-reduzierung` (Biggest Discount), `neuheiten` (New Arrivals), `bewertung` (Best Rated). |
| `minPrice` | integer | — | Only collect products priced at or above this amount, in euros. Leave empty for no lower limit. |
| `maxPrice` | integer | — | Only collect products priced at or below this amount, in euros. Leave empty for no upper limit. |
| `includeSponsored` | boolean | `false` | Otto mixes paid, sponsored products into its results (roughly 1 in 10). Leave off for a clean, ad-free product list. Turn on to get results exactly as a shopper sees them. Every product is labelled `organic` or `sponsored` either way. |

#### Limits

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `maxResults` | integer | `100` | Maximum number of products to return per search keyword or address. Set to `0` to collect everything available, up to a safety limit of 50,000 products per run. Products are collected about 120 at a time, so the final count is rounded up to the end of the last page. |

### Output

Each record is one product with up to 26 typed fields:

```json
{
    "productId": "1795988188",
    "variationId": "1795988189",
    "articleNumber": "7T3B4A0Q",
    "name": "T-Shirt (Packung, 3-tlg., 3er-Pack)",
    "brand": "TOM TAILOR",
    "productType": "organic",
    "url": "https://www.otto.de/p/tom-tailor-t-shirt-3er-pack-1795988188/#variationId=1795988189",
    "price": 23.99,
    "currency": "EUR",
    "comparativePrice": 24.99,
    "suggestedRetailPrice": 27.99,
    "isOnSale": true,
    "isStartingPrice": false,
    "discountPercent": 14.3,
    "rating": 4.6,
    "reviewCount": 218,
    "availability": "ORDERABLE",
    "availabilityDetail": "Lieferung in 2-4 Werktagen",
    "baseColor": "blau",
    "colors": ["Navy", "Weiß", "Schwarz"],
    "imageUrl": "https://i.otto.de/i/otto/1795988189",
    "sustainabilityBadges": ["Verbesserte Rohstoffbeschaffung"],
    "position": 7,
    "searchQuery": "shirt",
    "scrapedAt": "2026-07-17T09:14:22.481293+00:00"
}
```

Fields with no value are omitted from the record rather than returned as empty.

#### Product Identity

| Field | Type | Description |
|-------|------|-------------|
| `productId` | string | Otto's product identifier — stable across colourways of the same product. |
| `variationId` | string | Identifier for this specific variation (colour). Unique per record; results are de-duplicated on it. |
| `articleNumber` | string | Otto's article number, as shown on the product page. |
| `name` | string | Full product name, including pack and variant wording. |
| `brand` | string | Brand name (for example `TOM TAILOR`). |
| `productType` | string | `organic` for a normal result, `sponsored` for a paid placement. |
| `url` | string | Direct link to the product page on Otto.de. |

#### Pricing & Discount

| Field | Type | Description |
|-------|------|-------------|
| `price` | number | Current selling price in euros, parsed from Otto's German formatting (`1.399,00` → `1399.0`). |
| `currency` | string | Always `EUR`. |
| `comparativePrice` | number | Otto's compare-at (strike-through) price, when shown. |
| `suggestedRetailPrice` | number | Manufacturer's recommended retail price, when shown. |
| `isOnSale` | boolean | Whether Otto marks this product as on sale. |
| `isStartingPrice` | boolean | `true` when the price is a "from" price across variations rather than the exact price for this one. |
| `discountPercent` | number | Exact discount percentage computed against the higher of the compare-at price and the RRP, rather than Otto's display-only on-tile tag. Populated whenever a product has a higher reference price — around 3 in 4 products, and effectively all of them on the Biggest Discount sort. |

#### Ratings & Availability

| Field | Type | Description |
|-------|------|-------------|
| `rating` | number | Average customer rating out of 5. |
| `reviewCount` | integer | Total number of customer reviews behind that average. |
| `availability` | string | Stock state as Otto reports it (for example `ORDERABLE`). |
| `availabilityDetail` | string | Delivery detail text in German (for example `Lieferung in 2-4 Werktagen`). |

#### Variants & Media

| Field | Type | Description |
|-------|------|-------------|
| `baseColor` | string | Base colour of this variation, in German (for example `blau`). |
| `colors` | string\[] | Every colourway available for this product. |
| `imageUrl` | string | Product image. |
| `sustainabilityBadges` | string\[] | Otto's eco and sustainability labels, in readable German (for example `Verbesserte Rohstoffbeschaffung`). Present on roughly 2 in 3 products. |

#### Result Context

| Field | Type | Description |
|-------|------|-------------|
| `position` | integer | The product's rank in Otto's own result list for your sort order. |
| `searchQuery` | string | The keyword that produced this record. Present on keyword results. |
| `sourceUrl` | string | The pasted Otto.de address that produced this record. Present on address results. |
| `scrapedAt` | string | ISO 8601 timestamp of when the record was collected. |

### Tips for Best Results

- **Use German keywords** — Otto.de is a German marketplace, and its search matches German product wording. `kaffeevollautomat` returns a far richer result set than `coffee machine`. Umlauts and multi-word phrases such as `blaues hemd` work exactly as typed.
- **Sort deliberately when you set a limit** — Otto applies the sort order before you ever see the results, so a 500-product limit on Price: Low to High gives you the 500 cheapest matches, not 500 random ones. This is the single most useful lever in the whole input.
- **Biggest Discount is the deal-hunter's sort** — combined with a price band it produces a ready-to-use markdown feed. In testing, the top of a `hoechste-reduzierung` run sat at 82–84% off.
- **Treat `isStartingPrice: true` with care** — that price is a "from" figure across sizes or colours, not the exact price of that variation. Filter those rows out before doing exact price comparisons or you will understate the true price.
- **Results arrive about 120 at a time** — asking for 50 returns roughly 120, and you are charged for what you receive. Start with 100 to test the shape of the data, then raise the limit.
- **Paste addresses with your filters already applied** — click a brand or price facet on Otto.de in your browser, copy the address from the bar, and paste it in. Those facets are carried through, which is faster than recreating them here.
- **Leave sponsored results off unless you want them** — the default gives you a clean organic dataset. Turn them on only when measuring how much paid placement a category carries.

### Pricing

**From $1.20 per 1,000 results** — a flat rate per product returned, cheaper than the German marketplace alternatives. Bronze, Silver, and Gold subscribers pay progressively less; the table below shows total cost at each discount tier.

| Results | No discount | Bronze | Silver | Gold |
|---------|-------------|--------|--------|------|
| 100 | $0.14 | $0.135 | $0.13 | $0.12 |
| 1,000 | $1.40 | $1.35 | $1.30 | $1.20 |
| 10,000 | $14.00 | $13.50 | $13.00 | $12.00 |
| 100,000 | $140.00 | $135.00 | $130.00 | $120.00 |

A "result" is one product record in your dataset. **No compute or time-based charges — you pay per result, plus a small fixed per-run start fee.** Products filtered out before you receive them — those outside your price range, and sponsored placements you opted out of — are never charged for.

### Integrations

Export data in JSON, CSV, Excel, XML, or RSS. Connect to 1,500+ apps via:

- **Zapier** / **Make** / **n8n** — Workflow automation
- **Google Sheets** — Direct spreadsheet export
- **Slack** / **Email** — Notifications on new results
- **Webhooks** — Trigger custom APIs on run completion
- **Apify API** — Full programmatic access

### Legal & Ethical Use

This actor is built for legitimate price monitoring, market research, and competitive analysis on publicly available product listings. It collects no personal data — only product information that any visitor to Otto.de can see. You are responsible for complying with applicable laws and Otto.de's Terms of Service, for respecting copyright in product images and descriptions when redistributing them, and for using the collected data fairly. Do not use it for spam, misrepresentation, or any illegal purpose.

# Actor input Schema

## `searchQueries` (type: `array`):

Keywords to search on Otto.de, such as 'shirt' or 'kaffeevollautomat'. Each keyword runs its own search and we build the search for you — no need to create URLs. Leave empty if you are pasting Otto.de URLs below.

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

Paste Otto.de search or category page URLs, such as https://www.otto.de/suche/shirt/ or https://www.otto.de/damen/mode/shirts/. Both search and category pages are collected exactly as Otto scopes them, and any filters already in the pasted address (for example a price range) are kept. Leave empty if you are using search keywords above.

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

Order in which products are collected. Otto returns different products first depending on this, so it also changes which products you get when you set a result limit.

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

Only collect products priced at or above this amount, in euros. Leave empty for no lower limit. Otto applies this filter itself, so you are not billed for products outside your price range.

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

Only collect products priced at or below this amount, in euros. Leave empty for no upper limit. Otto applies this filter itself, so you are not billed for products outside your price range.

## `includeSponsored` (type: `boolean`):

Otto mixes paid, sponsored products into its results (roughly 1 in 10). Leave this off to get a clean, ad-free product list — this also means you are not billed for ad placements. Turn it on if you want results exactly as a shopper sees them on the site. Every product is labelled 'organic' or 'sponsored' in the output either way.

## `maxResults` (type: `integer`):

Maximum number of products to return per search keyword or URL. Set to 0 to collect everything available, up to a safety limit of 50,000 products per run. Products are collected about 120 at a time, so the final count is rounded up to the end of the last page — asking for 50 may return about 120. Every returned product is billed. Tip: start with 100 to test, then increase.

## Actor input object example

```json
{
  "searchQueries": [
    "shirt"
  ],
  "startUrls": [],
  "sortBy": "topseller",
  "maxResults": 100
}
```

# Actor output Schema

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

Key product fields: name, brand, price, discount, rating, availability and image.

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

Every collected field, including identifiers, full pricing breakdown, colors, image and sustainability badges.

# 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 = {
    "searchQueries": [
        "shirt"
    ],
    "startUrls": [],
    "sortBy": "topseller",
    "includeSponsored": false,
    "maxResults": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("solidcode/otto-de-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 = {
    "searchQueries": ["shirt"],
    "startUrls": [],
    "sortBy": "topseller",
    "includeSponsored": False,
    "maxResults": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("solidcode/otto-de-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchQueries": [
    "shirt"
  ],
  "startUrls": [],
  "sortBy": "topseller",
  "includeSponsored": false,
  "maxResults": 100
}' |
apify call solidcode/otto-de-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=solidcode/otto-de-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Otto.de Product Scraper",
        "description": "[💰 $1.2 / 1K] Scrape products from Otto.de, Germany's leading online marketplace: name, brand, price, compare-at price, discount, sale flags, rating, review count, availability, colors, images and sustainability badges. Search by keyword or paste Otto.de URLs, sort six ways, and skip sponsored ads",
        "version": "1.0",
        "x-build-id": "iNV4rhDbpNemINTqq"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/solidcode~otto-de-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-solidcode-otto-de-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/solidcode~otto-de-scraper/runs": {
            "post": {
                "operationId": "runs-sync-solidcode-otto-de-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/solidcode~otto-de-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-solidcode-otto-de-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "searchQueries": {
                        "title": "Search Keywords",
                        "type": "array",
                        "description": "Keywords to search on Otto.de, such as 'shirt' or 'kaffeevollautomat'. Each keyword runs its own search and we build the search for you — no need to create URLs. Leave empty if you are pasting Otto.de URLs below.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "startUrls": {
                        "title": "Otto.de URLs",
                        "type": "array",
                        "description": "Paste Otto.de search or category page URLs, such as https://www.otto.de/suche/shirt/ or https://www.otto.de/damen/mode/shirts/. Both search and category pages are collected exactly as Otto scopes them, and any filters already in the pasted address (for example a price range) are kept. Leave empty if you are using search keywords above.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "sortBy": {
                        "title": "Sort Results By",
                        "enum": [
                            "topseller",
                            "preis-aufsteigend",
                            "preis-absteigend",
                            "hoechste-reduzierung",
                            "neuheiten",
                            "bewertung"
                        ],
                        "type": "string",
                        "description": "Order in which products are collected. Otto returns different products first depending on this, so it also changes which products you get when you set a result limit."
                    },
                    "minPrice": {
                        "title": "Minimum Price (EUR)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Only collect products priced at or above this amount, in euros. Leave empty for no lower limit. Otto applies this filter itself, so you are not billed for products outside your price range."
                    },
                    "maxPrice": {
                        "title": "Maximum Price (EUR)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Only collect products priced at or below this amount, in euros. Leave empty for no upper limit. Otto applies this filter itself, so you are not billed for products outside your price range."
                    },
                    "includeSponsored": {
                        "title": "Include sponsored products",
                        "type": "boolean",
                        "description": "Otto mixes paid, sponsored products into its results (roughly 1 in 10). Leave this off to get a clean, ad-free product list — this also means you are not billed for ad placements. Turn it on if you want results exactly as a shopper sees them on the site. Every product is labelled 'organic' or 'sponsored' in the output either way."
                    },
                    "maxResults": {
                        "title": "Maximum Results",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Maximum number of products to return per search keyword or URL. Set to 0 to collect everything available, up to a safety limit of 50,000 products per run. Products are collected about 120 at a time, so the final count is rounded up to the end of the last page — asking for 50 may return about 120. Every returned product is billed. Tip: start with 100 to test, then increase."
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
