# Action Scraper — European Discount Retail Products & Prices (`studio-amba/action-scraper`) Actor

Scrape products, prices, and availability from Action.com. Europe's fastest-growing discount retailer across NL, BE, FR, DE, AT, PL, CZ, ES, IT, and more. Supports search, category browsing, and full catalog crawling.

- **URL**: https://apify.com/studio-amba/action-scraper.md
- **Developed by:** [Studio Amba](https://apify.com/studio-amba) (community)
- **Categories:** E-commerce
- **Features:** Limited permissions
- **Stats:** 6 total users, 2 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

## Action Scraper -- Europe's Biggest Discount Retailer at Your Fingertips

Know Action's current prices, stock, and new arrivals across 17 European locales without opening the site yourself. From household essentials to seasonal bargains, this scraper turns Action's full catalog into structured JSON you can pull on a schedule.

### What is Action Scraper?

Action is Europe's fastest-growing non-food discount retailer, operating over 2,500 stores in 12 countries. Their product range rotates constantly, with new items arriving weekly at rock-bottom prices. This scraper gives you programmatic access to that data.

Here's what people use it for:

- **Price monitoring at scale** -- Track Action's notoriously volatile pricing across Belgium, Netherlands, France, Germany, and 12 other markets. Spot when your competitor's products drop below the euro threshold.
- **Product discovery** -- Action's assortment changes weekly. Automated scraping catches new arrivals before they sell out, whether you're a reseller, a deal blogger, or just curious.
- **Cross-border price comparison** -- The same item can cost differently in Action Belgium vs Action France. Compare prices across all 16 locales in a single run.
- **Discount & deal tracking** -- Action's "deals" and "new arrivals" rotate fast. Build alerts for specific categories or price drops.
- **Retail competitive intelligence** -- If you sell household goods, DIY supplies, or seasonal items, Action's pricing sets the floor. Know what that floor is.

### What data does Action Scraper extract?

Every product comes with a rich set of fields:

- 🏷️ **Product name** and description
- 💰 **Current price** and original price (when on sale)
- 📊 **Price per unit** (e.g., "EUR 0.50/L")
- 🏪 **Stock status** -- online availability (`true`/`false`; `null` when the site gives no signal)
- 🆕 **New arrival flag** -- freshly added items
- 🔥 **Deal flag** -- currently discounted
- 🖼️ **Product images** -- main image + all gallery images
- 📂 **Category** -- the category path a product was found under (category and full-catalog modes; search results carry no category)
- 🔢 **SKU and product ID** -- unique identifiers
- 💱 **Currency** -- EUR for most markets
- 🌍 **Language/locale** -- which country site the data came from

### How to scrape Action.com

The scraper supports three input modes. Pick the one that fits your use case.

#### Search by keyword

Find products matching a search term. Good for targeted extraction.

```json
{
    "searchQuery": "lamp",
    "locale": "nl-be",
    "maxResults": 50
}
```

#### Browse by category or product URL

Pass one or more Action.com URLs -- category pages or individual product pages.

```json
{
    "startUrls": [
        { "url": "https://www.action.com/nl-be/c/huishouden/" }
    ],
    "maxResults": 200
}
```

Action reorganizes its category tree regularly, so copy current category URLs from the site. A stale category URL produces a clear "Category URL not found" error in the run log.

Product URLs (`/p/...`) are resolved through the site's search when Action blocks direct product-page access, so they work in both cases. Each resolved product carries the same fields as search results.

**Precedence:** when both `searchQuery` and `startUrls` are filled in, `searchQuery` wins and `startUrls` are ignored. The run log states this explicitly. Clear the search field to scrape your URLs.

#### Full catalog scrape

Enable `scrapeFullCatalog` to crawl every top-level category and collect the full assortment, deduplicated by product ID. Action carries roughly 4,000-6,000 unique products per locale. This ignores `startUrls` and `searchQuery`. Set `maxResults` above the catalog size or the run stops at the cap.

```json
{
    "scrapeFullCatalog": true,
    "locale": "nl-nl",
    "maxResults": 10000
}
```

#### Locale options

Action operates in 17 locales. Set the `locale` field to target a specific country:

| Locale | Country |
|--------|---------|
| `nl-be` | Belgium (Dutch) |
| `fr-be` | Belgium (French) |
| `nl-nl` | Netherlands |
| `fr-fr` | France |
| `de-de` | Germany |
| `de-at` | Austria |
| `pl-pl` | Poland |
| `cs-cz` | Czech Republic |
| `es-es` | Spain |
| `it-it` | Italy |
| `fr-lu` | Luxembourg |
| `pt-pt` | Portugal |
| `sk-sk` | Slovakia |
| `ro-ro` | Romania |
| `hr-hr` | Croatia |
| `de-ch` | Switzerland (German) |
| `fr-ch` | Switzerland (French) |

**Tip:** Run the same search across multiple locales to compare regional pricing. Action's assortment and pricing vary significantly between countries.

### Output

Each product is returned as a JSON object. Here is a realistic example from Action Belgium:

```json
{
    "name": "LED bureaulamp met flexibele arm",
    "brand": "",
    "price": 4.29,
    "currency": "EUR",
    "url": "https://www.action.com/nl-be/p/3254891/led-bureaulamp-met-flexibele-arm/",
    "scrapedAt": "2025-04-03T10:30:00.000Z",
    "originalPrice": 5.95,
    "pricePerUnit": "EUR 4,29/stuk",
    "sku": "3254891",
    "productId": "prod-3254891",
    "inStock": true,
    "isNew": false,
    "isDeal": true,
    "imageUrl": "https://asset.action.com/image/upload/t_digital_product_image/w_640/led-bureaulamp.webp",
    "imageUrls": [
        "https://asset.action.com/image/upload/t_digital_product_image/w_640/led-bureaulamp.webp",
        "https://asset.action.com/image/upload/t_digital_product_image/w_640/led-bureaulamp-2.webp"
    ],
    "description": "Flexibele arm | USB-aansluiting | diverse kleuren",
    "category": "huishouden",
    "categories": ["huishouden"],
    "language": "nl"
}
```

The `category`/`categories` fields are set when scraping category URLs or the full catalog (the category path the product was found under). Search results and product-URL lookups omit them.

### How much does it cost?

Action Scraper uses pay-per-event pricing: $0.02 per Actor start (charged per GB of memory, 4 events at this actor's 4 GB default) plus $0.002 per scraped product. Platform usage (compute, proxy) is included in these prices.

| Scenario | Cost |
|----------|------|
| 100 products (search or category) | ~$0.22 |
| 500 products (multiple categories) | ~$1.02 |
| Full catalog (~5,500 products) | ~$11.02 |

A run's charges only settle once it finishes. If a run fails, you are charged for the results it delivered before failing.

### Can I integrate?

Apify integrates natively with the tools you already use:

- **Google Sheets** -- push scraped data directly into a spreadsheet
- **Webhooks** -- trigger your pipeline when a run finishes
- **Zapier / Make** -- connect Action data to 5,000+ apps
- **Slack** -- get notified about new deals or price drops
- **Amazon S3 / Google Cloud Storage** -- export datasets to cloud storage
- **PostgreSQL / MySQL** -- store results in your own database

### Can I use it as an API?

Yes. Call Action Scraper programmatically from any language.

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_API_TOKEN")

run = client.actor("studio-amba/action-scraper").call(run_input={
    "searchQuery": "stofzuiger",
    "locale": "nl-be",
    "maxResults": 25,
})

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(f"{item['name']} -- EUR {item['price']}")
```

#### JavaScript

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

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

const run = await client.actor('studio-amba/action-scraper').call({
    searchQuery: 'stofzuiger',
    locale: 'nl-be',
    maxResults: 25,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach(item => console.log(`${item.name} -- EUR ${item.price}`));
```

### FAQ

**Does this scraper work without a proxy?**
On the Apify platform it uses Belgian residential proxy by default, and that is the reliable setup -- Action.com's Cloudflare protection blocks datacenter IPs. Leave the default proxy configuration in place.

**How often does Action update their product catalog?**
Action adds new products weekly and rotates seasonal items frequently. Running the scraper daily or weekly captures most changes.

**Can I scrape multiple countries in one run?**
The `locale` field applies to a single run. To compare across countries, run the scraper once per locale. You can orchestrate this with the Apify API or scheduler.

**What happens if a product is out of stock?**
Out-of-stock products still appear in results with `inStock: false`. This is useful for tracking availability over time.

**Does the scraper handle pagination automatically?**
Yes. For search and category pages, pagination is followed automatically until `maxResults` is reached.

**Why are some product descriptions short?**
Descriptions come from Action's listing data, which carries a spec-style summary (e.g. "3 stuks | Maten 35-46 | diverse kleuren") rather than long marketing text. That is what the site exposes on listings.

### Limitations

- Action.com uses Cloudflare protection. Search and category pages pass with the default residential proxy; direct product-page fetches are blocked, so product URLs are resolved through the site's search instead. If most requested products cannot be delivered, the run fails loudly rather than reporting success on partial data.
- Product availability data reflects online stock, not individual store inventory.
- Some fields (like `pricePerUnit`) are only available for certain product types.
- The `category` field reflects the category page a product was found under, not a per-product breadcrumb. Search results and product-URL lookups carry no category.
- Action reorganizes its category URLs regularly. A stale category URL logs a clear 404 error -- copy fresh URLs from the site.

### Other retail and fashion scrapers

Looking for data from other European retailers? Check out these scrapers from our collection:

- [Mytheresa Scraper](https://apify.com/studio-amba/mytheresa-scraper) -- Luxury fashion products and prices
- [Rituals Scraper](https://apify.com/studio-amba/rituals-scraper) -- Premium cosmetics and home fragrance
- [Kruidvat Scraper](https://apify.com/studio-amba/kruidvat-scraper) -- Drugstore, beauty, and health products
- [ICI PARIS XL Scraper](https://apify.com/studio-amba/iciparisxl-scraper) -- Belgian beauty and perfume retailer
- [AS Adventure Scraper](https://apify.com/studio-amba/asadventure-scraper) -- Outdoor and adventure gear
- [Bergfreunde Scraper](https://apify.com/studio-amba/bergfreunde-scraper) -- Climbing and hiking equipment
- [Intersport Scraper](https://apify.com/studio-amba/intersport-scraper) -- European sports retail
- [Helly Hansen Scraper](https://apify.com/studio-amba/hellyhansen-scraper) -- Outdoor and sailing apparel

### Your feedback

Found a bug? Missing a field? Want a feature? Open an issue on the actor's page or reach out through the Apify platform. We actively maintain this scraper and ship fixes fast.

# Actor input Schema

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

Category or product URLs from action.com. Example: https://www.action.com/nl-be/c/huishouden/ or https://www.action.com/nl-be/p/3220586/letterponsbord/. Action reorganizes its category tree regularly — copy current category URLs from the site. Ignored when Search Query is filled in.

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

Search for products by keyword (e.g., 'lamp', 'stofzuiger'). Uses the site's search functionality. Takes precedence over Start URLs when both are set. Leave empty and without Start URLs to scrape the homepage.

## `locale` (type: `string`):

Which Action country site to scrape. Determines language and product availability.

## `scrapeFullCatalog` (type: `boolean`):

If enabled, crawls every top-level category and collects the full assortment (roughly 4,000-6,000 unique products per locale). Ignores startUrls and searchQuery. Set maxResults high enough (e.g. 10000) or the run stops at the cap.

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

Maximum number of products to return.

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

Proxy settings. Action.com blocks datacenter IPs. Leave the default Belgian residential proxy in place.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.action.com/nl-be/c/huishouden/"
    }
  ],
  "locale": "nl-be",
  "scrapeFullCatalog": false,
  "maxResults": 100,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "BE"
  }
}
```

# 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 = {
    "startUrls": [
        {
            "url": "https://www.action.com/nl-be/c/huishouden/"
        }
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "BE"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("studio-amba/action-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 = {
    "startUrls": [{ "url": "https://www.action.com/nl-be/c/huishouden/" }],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "BE",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("studio-amba/action-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 '{
  "startUrls": [
    {
      "url": "https://www.action.com/nl-be/c/huishouden/"
    }
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "BE"
  }
}' |
apify call studio-amba/action-scraper --silent --output-dataset

```

## MCP server setup

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