# Apotea Scraper — Swedish Online Pharmacy Products & Prices (`studio-amba/apotea-scraper`) Actor

Scrape Sweden's largest online pharmacy, Apotea.se. Get product names, prices, brands, EANs, ratings, stock status, and images for medications and health products.

- **URL**: https://apify.com/studio-amba/apotea-scraper.md
- **Developed by:** [Jelle Desramaults](https://apify.com/studio-amba) (community)
- **Categories:** E-commerce
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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/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.md):

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

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.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/platform/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

## Apotea Scraper -- Sweden's Largest Online Pharmacy: Products, Prices & Stock Data

Extract products, prices, brands, EAN codes, ratings, availability, and descriptions from [Apotea.se](https://www.apotea.se) -- Sweden's biggest online pharmacy and health products retailer, offering over 15,000 products ranging from prescription-free medications and vitamins to skincare, baby care, and wellness products.

### What is Apotea Scraper?

Apotea disrupted the Swedish pharmacy market when prescription drug sales were deregulated. Today, it is Sweden's largest online pharmacy by volume, known for competitive pricing, fast delivery, and an enormous catalogue of health-related products. The platform is the primary pricing reference for the Swedish pharmacy and wellness market.

This actor handles Apotea's Cloudflare protection using TLS fingerprint rotation via got-scraping, with automatic fallback to CheerioCrawler. It extracts product data from both JSON-LD structured data and HTML parsing across search results, category pages, and individual product pages. What people build with it:

- **Pharmacy pricing intelligence** -- competing pharmacies (Apotek Hjartat, Kronans Apotek, Lloyds Apotek) monitor Apotea's prices to maintain market-competitive positioning in the Swedish pharmacy sector.
- **Health product market research** -- consumer health brands and supplement manufacturers track how their products are priced, described, and rated on Sweden's largest pharmacy platform.
- **Regulatory compliance monitoring** -- pharmaceutical industry bodies track which products are available on Apotea, at what prices, and how they are marketed to consumers.
- **Product catalogue enrichment** -- health tech platforms and comparison sites use Apotea's structured product data (EAN codes, descriptions, images) to populate their own databases.
- **Consumer trend analysis** -- market researchers analyse Apotea's category structure, bestsellers, and ratings to understand Swedish consumer health and wellness preferences.

### What data does Apotea Scraper extract?

Each product record includes:

- :pill: **Product name** -- full product title in Swedish
- :label: **Brand** -- manufacturer or brand name
- :moneybag: **Price** -- current price in SEK (Swedish kronor)
- :money_with_wings: **Original price** -- regular price if the product is on sale
- :currency_exchange: **Currency** -- SEK
- :barcode: **EAN code** -- GTIN barcode for product identification
- :id: **SKU and product ID** -- internal product identifiers
- :white_check_mark: **Stock status** -- whether the product is in stock
- :star: **Rating** -- user rating score
- :speech_balloon: **Review count** -- number of customer reviews
- :camera: **Images** -- primary image and full gallery URLs
- :page_facing_up: **Description** -- product description text
- :file_folder: **Category and breadcrumbs** -- full category path in Apotea's taxonomy
- :globe_with_meridians: **Language** -- `"sv"` (Swedish)
- :link: **URL** -- direct product link on apotea.se

### How to scrape Apotea.se

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `searchQuery` | String | No | Search by keyword: `"vitamin"`, `"ibuprofen"`, `"solskydd"` (sunscreen) |
| `categoryUrl` | String | No | Apotea category URL, e.g. `https://www.apotea.se/kategori/vitaminer-mineraler` |
| `maxResults` | Integer | No | Maximum products to return (default: 100, max: 10,000) |
| `proxyConfiguration` | Object | No | Proxy settings (residential proxies recommended for Cloudflare bypass) |

**Tips:**

- Use **Swedish keywords** for best coverage: `"vitaminer"` (vitamins), `"hudvard"` (skincare), `"tandvard"` (dental care), `"barnprodukter"` (baby products).
- Apotea uses Cloudflare Turnstile protection. **Residential proxies** significantly improve success rates compared to datacenter proxies.
- For category-wide scraping, browse apotea.se to find the category URL and paste it into `categoryUrl`.
- The actor automatically tries got-scraping (TLS fingerprint rotation) first, falling back to CheerioCrawler if needed.

### Output

```json
{
    "name": "Apotea Vitamin D3 2000 IE 90 kapslar",
    "brand": "Apotea",
    "price": 79,
    "originalPrice": 99,
    "currency": "SEK",
    "ean": "7350083590123",
    "sku": "APT-VD3-90",
    "inStock": true,
    "rating": 4.6,
    "reviewCount": 1247,
    "imageUrl": "https://www.apotea.se/media/products/vitamin-d3-2000ie.jpg",
    "imageUrls": [
        "https://www.apotea.se/media/products/vitamin-d3-2000ie.jpg",
        "https://www.apotea.se/media/products/vitamin-d3-2000ie-back.jpg"
    ],
    "description": "Vitamin D3 i kapselform for dagligt bruk. Varje kapsel innehaller 2000 IE (50 mikrogram) vitamin D3. Bidrar till normal funktion av immunsystemet...",
    "category": "Vitaminer > Vitamin D",
    "categories": ["Halsa", "Vitaminer & mineraler", "Vitamin D"],
    "language": "sv",
    "url": "https://www.apotea.se/apotea-vitamin-d3-2000ie-90-kapslar",
    "scrapedAt": "2026-04-03T17:00:00.000Z"
}
````

### How much does it cost?

Costs vary depending on whether got-scraping or CheerioCrawler handles the requests:

| Volume | Estimated CUs | Estimated Cost |
|--------|--------------|----------------|
| 100 products | ~0.05 | ~$0.025 |
| 500 products | ~0.20 | ~$0.10 |
| 1,000 products | ~0.40 | ~$0.20 |
| 5,000 products | ~1.80 | ~$0.90 |

Cloudflare bypass attempts may increase compute costs. Residential proxies add to the per-request proxy cost but improve reliability.

### Can I integrate?

Connect Swedish pharmacy data to your tools:

- **Google Sheets** -- track prices on your product portfolio across the Swedish pharmacy market
- **Slack** -- get alerts when specific health products go on sale on Apotea
- **Zapier / Make** -- automate pricing updates for your competing pharmacy or health store
- **Webhooks** -- stream product data to your own health product comparison platform
- **PostgreSQL / BigQuery** -- build a historical Swedish health product pricing database
- **Power BI** -- visualise pricing trends in Swedish pharmacy categories

### Can I use it as an API?

Yes. Build Swedish health product intelligence into your stack:

**Python:**

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_API_TOKEN")

run = client.actor("studio-amba/apotea-scraper").call(run_input={
    "searchQuery": "vitamin C",
    "maxResults": 50,
    "proxyConfiguration": {"useApifyProxy": True, "apifyProxyGroups": ["RESIDENTIAL"]},
})

for product in client.dataset(run["defaultDatasetId"]).iterate_items():
    stock = "I lager" if product.get('inStock') else "Slut"
    print(f"{product['name']} | {product['price']} SEK | {stock}")
```

**JavaScript:**

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

const client = new ApifyClient({ token: "YOUR_API_TOKEN" });

const run = await client.actor("studio-amba/apotea-scraper").call({
    searchQuery: "vitamin C",
    maxResults: 50,
    proxyConfiguration: { useApifyProxy: true, apifyProxyGroups: ["RESIDENTIAL"] },
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
const onSale = items.filter((p) => p.originalPrice && p.originalPrice > p.price);
console.log(`${onSale.length} products on sale:`);
onSale.forEach((p) => {
    const discount = Math.round((1 - p.price / p.originalPrice) * 100);
    console.log(`  ${p.name} | ${p.price} SEK (was ${p.originalPrice}, -${discount}%)`);
});
```

### FAQ

**Does Apotea sell prescription medications?**
Apotea sells both prescription-free (receptfria) medications and prescription drugs. This actor scrapes product data from public product pages, which are primarily non-prescription items, supplements, and health products.

**Is all data in Swedish?**
Yes. Product names, descriptions, and categories are in Swedish. The platform serves the Swedish market exclusively.

**Why do I need residential proxies?**
Apotea.se uses Cloudflare Turnstile protection. Residential proxies have a much higher success rate at bypassing this protection compared to datacenter proxies. The actor will still work without residential proxies, but success rates may be lower.

**Can I get prices without proxy?**
The actor tests whether direct HTTP access works on each run. If Cloudflare is not actively challenging your IP, it works without proxies. However, for reliable production use, residential proxies are strongly recommended.

**How does the dual scraping strategy work?**
The actor first attempts direct HTTP requests using got-scraping (which rotates TLS fingerprints). If Cloudflare blocks this, it falls back to CheerioCrawler with the configured proxy. This dual approach maximises success rates.

**Does it capture product dosage and active ingredients?**
These details are typically in the product description text. The actor does not parse them into separate structured fields -- they remain in the description string.

### Limitations

- Apotea.se uses Cloudflare Turnstile. Without residential proxies, success rates may be inconsistent.
- Product card extraction from listing pages may not capture all fields. The actor enqueues individual product pages for full detail extraction when card data is incomplete.
- Categories and product structures may change as Apotea updates their website.
- Not all products have EAN codes, ratings, or reviews in their JSON-LD data.
- The actor caps pagination at 50 pages as a safety measure to prevent infinite loops.

### Related Swedish and European pharmacy scrapers

- [Apotek Hjartat Scraper](https://apify.com/studio-amba/apotekhjartat-scraper) -- Sweden's second-largest pharmacy chain with 390+ physical stores
- [Prisjakt Scraper](https://apify.com/studio-amba/prisjakt-scraper) -- Nordic price comparison across all product categories
- [Ceneo Scraper](https://apify.com/studio-amba/ceneo-scraper) -- Polish price comparison (for European health product pricing analysis)

### Your feedback

Need specific health product categories, deeper product specification parsing, or price history tracking? Open an issue on GitHub or contact us through the Apify platform. We build what users need.

# Actor input Schema

## `searchQuery` (type: `string`):

Search for products by keyword (e.g., 'vitamin', 'ibuprofen', 'solskydd'). Uses Apotea's search page.

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

An Apotea category page URL to scrape. Example: https://www.apotea.se/kategori/vitaminer-mineraler. If empty and no search query, the actor will not run.

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

Maximum number of products to return.

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

Proxy settings. Recommended: use Apify residential proxies for best results against Cloudflare.

## Actor input object example

```json
{
  "searchQuery": "vitamin",
  "maxResults": 100
}
```

# 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 = {
    "searchQuery": "vitamin"
};

// Run the Actor and wait for it to finish
const run = await client.actor("studio-amba/apotea-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 = { "searchQuery": "vitamin" }

# Run the Actor and wait for it to finish
run = client.actor("studio-amba/apotea-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 '{
  "searchQuery": "vitamin"
}' |
apify call studio-amba/apotea-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Apotea Scraper — Swedish Online Pharmacy Products & Prices",
        "description": "Scrape Sweden's largest online pharmacy, Apotea.se. Get product names, prices, brands, EANs, ratings, stock status, and images for medications and health products.",
        "version": "0.1",
        "x-build-id": "EwvbxfF0WquFffPN5"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/studio-amba~apotea-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-studio-amba-apotea-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/studio-amba~apotea-scraper/runs": {
            "post": {
                "operationId": "runs-sync-studio-amba-apotea-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/studio-amba~apotea-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-studio-amba-apotea-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": {
                    "searchQuery": {
                        "title": "Search Query",
                        "type": "string",
                        "description": "Search for products by keyword (e.g., 'vitamin', 'ibuprofen', 'solskydd'). Uses Apotea's search page."
                    },
                    "categoryUrl": {
                        "title": "Category URL",
                        "type": "string",
                        "description": "An Apotea category page URL to scrape. Example: https://www.apotea.se/kategori/vitaminer-mineraler. If empty and no search query, the actor will not run."
                    },
                    "maxResults": {
                        "title": "Max Results",
                        "minimum": 1,
                        "maximum": 10000,
                        "type": "integer",
                        "description": "Maximum number of products to return.",
                        "default": 100
                    },
                    "proxyConfiguration": {
                        "title": "Proxy Configuration",
                        "type": "object",
                        "description": "Proxy settings. Recommended: use Apify residential proxies for best results against Cloudflare."
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
