# Bilka Scraper — Danish Hypermarket Products & Prices (`studio-amba/bilka-scraper`) Actor

Scrape products, prices, and availability from Bilka.dk — Denmark's largest hypermarket chain. Electronics, groceries, home, fashion, and more.

- **URL**: https://apify.com/studio-amba/bilka-scraper.md
- **Developed by:** [Studio Amba](https://apify.com/studio-amba) (community)
- **Categories:** E-commerce
- **Features:** Limited permissions
- **Stats:** 3 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 result scrapeds

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

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

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

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Bilka Scraper

Scrape products from bilka.dk, Denmark's largest hypermarket chain (owned by Salling Group, alongside Netto and Føtex — the same Algolia backend as [Føtex Scraper](https://apify.com/studio-amba/foetex-scraper)). Electronics, home appliances, toys, garden, fashion, wine and dry goods — Bilka carries a massive range.

**Catalogue scope**: `searchQuery` and `categoryUrl` both read bilka.dk's own product catalogue and search index — the same one the on-site search box and category pages use. That catalogue covers non-perishable groceries (coffee, tea, canned goods, spices), beverages, wine and spirits, and general merchandise (electronics, home, garden, toys, fashion). Fresh and chilled groceries (milk, bread, butter, eggs, meat, produce) are sold in Bilka stores but are not part of the online catalogue this Actor reads, so they will not appear in results.

### Input

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `searchQuery` | String | No | Danish keyword, e.g. `"laptop"`, `"samsung tv"`, `"kaffe"`. Queries Bilka's own product search directly. |
| `categoryUrl` | String | No | A Bilka.dk category listing URL (e.g. `https://www.bilka.dk/elektronik/tv-foto-og-lyd/tv/pl/tv/`) or a direct product URL. Takes priority over `searchQuery`. |
| `maxResults` | Integer | No | Product limit (default: 100) |
| `proxyConfiguration` | Object | No | Proxy settings — used for `categoryUrl` mode and direct product-page fetches; not required for `searchQuery` mode, which calls the search API directly. |

### Output

| Field | Type | Example |
|-------|------|---------|
| `name` | String | `"Samsung 55\" QLED 4K Smart TV"` |
| `brand` | String | `"Samsung"` |
| `price` | Number | `4999.00` |
| `originalPrice` | Number or null | `5999.00` |
| `currency` | String | `"DKK"` |
| `sku` | String or null | Product SKU |
| `ean` | String or null | EAN / GTIN barcode |
| `productId` | String or null | Internal Bilka/Salling Group product id |
| `inStock` | Boolean or null | `true` (null when the site reports no stock signal at all) |
| `pricePerUnit` | String or null | `"35,00 kr/L"` |
| `unitPrice` | Number or null | `35.00` |
| `unitPriceUnit` | String or null | `"L"` |
| `packageSize` | String or null | `"500 ml"` |
| `onPromotion` | Boolean | `true` |
| `promotionStartDate` | String or null | `"2026-08-24"` |
| `promotionEndDate` | String or null | `"2026-09-24"` |
| `rating` | Number or null | `4.5` |
| `reviewCount` | Number or null | `12` |
| `imageUrl` | String or null | Product image |
| `imageUrls` | Array | All gallery image URLs |
| `description` | String or null | Product description |
| `category` | String or null | `"Elektronik > TV og tilbehør"` |
| `categories` | Array | Category path as a list |
| `retailer` | String or null | `"bilka"` |
| `url` | String | Direct product page URL |
| `scrapedAt` | String | ISO timestamp when this Actor run collected the item |
| `sourceUpdatedAt` | String or null | ISO timestamp Bilka's own catalogue last updated the record (Algolia listings only) |

```json
{
    "name": "Samsung 55\" QLED 4K Smart TV",
    "brand": "Samsung",
    "price": 4999.00,
    "originalPrice": 5999.00,
    "currency": "DKK",
    "ean": "8806094123456",
    "productId": "200123456",
    "inStock": true,
    "onPromotion": true,
    "promotionStartDate": null,
    "promotionEndDate": null,
    "imageUrl": "https://digitalassets.sallinggroup.com/image/upload/...",
    "category": "Elektronik > TV og tilbehør",
    "categories": ["Elektronik", "TV og tilbehør"],
    "retailer": "bilka",
    "url": "https://www.bilka.dk/produkter/samsung-55-qled-tv/200123456/",
    "scrapedAt": "2026-09-09T10:00:00.000Z",
    "sourceUpdatedAt": "2026-09-08T06:12:00.000Z"
}
```

`price` is the current shelf/online price and `originalPrice` is the pre-discount list price — when `originalPrice` is set (or `onPromotion` is `true`), the product is on an active campaign and `promotionStartDate` / `promotionEndDate` give the campaign window as published by Bilka.

### Technical details

- `searchQuery` mode queries Bilka's own Algolia search index directly (the same one the on-site search box uses) — no proxy or browser needed.
- `categoryUrl` mode reads the Algolia filter a `/pl/` category page hydrates its grid with, then queries the same index — falls back to scraping server-rendered product links if a page carries no Algolia filter. A direct `/produkter/` URL is scraped as a single product page (JSON-LD, with an HTML-selector fallback).
- Prices in DKK (Danish kroner)
- Danish-language content throughout

### Cost

Direct API calls for search and category modes; a browser launch only when a category page's Algolia filter needs to be read. **~$0.25 per 1,000 products.**

### Why use Bilka Scraper

- **Price monitoring** — Track prices, stock, and promotions across Bilka at scale
- **Competitive intelligence** — Compare your catalog against Bilka pricing and assortment
- **Market research** — Analyze category trends, new arrivals, and rating distributions
- **Lead generation** — Build product datasets for affiliate sites, comparison tools, or feeds
- **No login or cookies required** — Authenticated access not needed; works out of the box

### How to use Bilka Scraper

1. Open the **Input** tab and provide a search query or a category URL
2. Adjust optional filters such as `maxResults` or proxy settings
3. Click **Start** and wait for the run to complete
4. Download results from the **Output** tab in JSON, CSV, Excel, XML, or HTML
5. Schedule recurring runs from the **Schedule** tab if you need ongoing data

### How to scrape Bilka data

This Actor automates the process of extracting structured product data from Bilka.
You can run it directly from the Apify console, the Apify API, or any of the
official SDKs (JavaScript, Python). The scraper handles pagination, retries, and
rate limiting so you can focus on the data, not the plumbing.

Typical workflows:

- **One-off export**: paste a category URL or keyword, set `maxResults`, and run
- **Scheduled monitoring**: set a daily cron in the Schedule tab to track prices over time
- **Programmatic integration**: trigger runs from your backend via the Apify API and
  pull the dataset when finished
- **Webhook automation**: receive a callback the moment a run completes and pipe
  the results into Zapier, Make, n8n, BigQuery, or Google Sheets

### Tips for best results

- **Start small** — run with `maxResults: 10` before launching large jobs
- **Use proxies for `categoryUrl`** — residential proxies reduce blocking on the category-page browser step
- **Throttle on big jobs** — a large `maxResults` on `categoryUrl` mode paces through Algolia pagination; keep expectations realistic for very broad categories
- **Schedule runs** — daily runs are usually enough for price monitoring
- **Inspect the dataset schema** — the Storage tab shows the full output structure

### FAQ and support

**Is it legal to scrape Bilka?** This Actor extracts publicly available data.
Always review the website's Terms of Service before scraping at scale, and
respect rate limits.

**Why am I getting fewer results than expected?** Some niche keywords or categories
have few matches in the catalogue, and fresh/chilled groceries aren't in the online
catalogue at all (see Catalogue scope above). Try a broader Danish term or increase
`maxResults`.

**Can I extract data for a single product?** Yes — pass the full product page URL
(e.g. `https://www.bilka.dk/produkter/.../123456/`) as `categoryUrl` and the scraper
returns that one item.

**The site blocks me — what should I do?** Enable Apify residential proxies in
the input for `categoryUrl` mode. Datacenter IPs are blocked by many e-commerce sites.

For issues, feature requests, or bug reports, open a ticket in the Issues tab on
the Actor page or contact support@apify.com. We monitor every actor and ship
fixes quickly when sites change.

# Actor input Schema

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

Search for products by keyword (e.g., 'laptop', 'samsung tv'). Uses Bilka's search page.

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

A Bilka.dk category page URL to scrape. Example: https://www.bilka.dk/elektronik. Leave empty to use search query instead.

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

Maximum number of products to return.

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

Proxy settings for better reliability.

## Actor input object example

```json
{
  "searchQuery": "laptop",
  "maxResults": 100,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "DK"
  }
}
```

# Actor output Schema

## `results` (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 = {
    "searchQuery": "laptop",
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "DK"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("studio-amba/bilka-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": "laptop",
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "DK",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("studio-amba/bilka-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 '{
  "searchQuery": "laptop",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "DK"
  }
}' |
apify call studio-amba/bilka-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,studio-amba/bilka-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/vhwaRktEr5Uf2SMvr/builds/w7S1WP6k5Mc1awBfq/openapi.json
