# Salla Store Catalog & Price Scraper (`abdulwhab95/salla-catalog-scraper`) Actor

Products, prices and stock from any Salla store. Give it a normal store link - it works out the API identifier itself. HTTP only, no browser, no key.

- **URL**: https://apify.com/abdulwhab95/salla-catalog-scraper.md
- **Developed by:** [ABDULWAHAB NASER RASHED ALQARAWI](https://apify.com/abdulwhab95) (community)
- **Categories:** E-commerce, Lead generation
- **Stats:** 3 total users, 2 monthly users, 80.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.50 / 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.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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

## Salla Store Catalog & Price Scraper

Products, prices and stock from **any Salla store** — Saudi Arabia's largest
e-commerce platform.

Give it a normal store link. No API key, no browser, no proxy.

***

### The identifier problem, solved

Salla's API needs a `Store-Identifier` header that no shop owner has ever seen.
An Actor that asks you for it is asking for something you do not have.

This one works it out from the public store page. All of these work:

```
salla.sa/coffee_souq
otor200sa.com
https://otor200sa.com/ar/xvXnyXK
coffee_souq
```

***

### What you get

One row per product, **29 fields, every one always present** — missing values
come back as `null`, never dropped.

| Field | Example |
|---|---|
| `name` | مجموعة أورموند جين فيستيف كاليندر |
| `price` | `1150.0` |
| `regularPrice` | `1955.0` |
| `currency` | `SAR` |
| `isOnSale` | `true` |
| `discountPct` | `41.18` |
| `isOutOfStock` | `true` |
| `category` | للجنسين |

Plus `productId`, `sku`, `gtin`, `mpn`, `salePrice`, `discountStarts`,
`discountEnds`, `isAvailable`, `quantity`, `unlimitedQuantity`, `brand`,
`productType`, `status`, `tags`, `rating`, `weight`, `imageUrl`, `hasOptions`,
`productUrl`, `store`, `scrapedAt`.

**A real discount, not a claimed one.** Some stores set the on-sale flag with
both prices equal; `discountPct` is filled only when the regular price is
genuinely higher.

***

### Use it for

- **Competitor price monitoring** — schedule it, diff the `price` column
- **Discount tracking** — set `onlyOnSale`, sort by `discountPct`
- **Stock-out alerts** — watch `isOutOfStock` flip
- **Catalog and market research** across Saudi and Gulf stores

***

### Speed

Measured, 1 Sep 2026: **0.23s per page of 15 products.**

```
  500 products   ~8 seconds
1,000 products   ~20 seconds
3,000 products   ~50 seconds
```

***

### Honest notes

**Pagination is cursor-only.** `page=` is ignored and `per_page` is capped at 15
by the API — not by this Actor. The cursor is walked for you.

**Not every store resolves.** Custom domains with unusual themes may not expose
the identifier. Unresolved stores are listed in the run report under
`unresolved` rather than failing the run silently — pass the `salla.sa/<slug>`
form for those.

**No personal data.** The payload's `availability_notify` block holds booleans
about notification channels, not anyone's contact details. Nothing identifying
a person is collected.

**robots.txt is read before anything else.** `api.salla.dev` allows a normal
agent on this path and disallows a named list of AI crawlers; this Actor ships
its own identifier and honours the file.

**Every run publishes a report** to the key-value store under `RUN_REPORT`:
requests, rows, stores reached, unresolved stores, and cost per 1,000 rows.

***

### Questions, or a store that will not resolve?

Open an issue with the store link. Most failures are one store's theme, and
they are usually quick to fix.

# Actor input Schema

## `stores` (type: `array`):

One store per line. A salla.sa link, the store's own domain, or just the slug - all work. The Actor works out the API identifier itself.

## `maxProductsPerStore` (type: `integer`):

Stop after this many products from each store.

## `onlyOnSale` (type: `boolean`):

Return only products currently on sale - useful for discount monitoring.

## `requestDelayMs` (type: `integer`):

Politeness. 200ms is comfortable; lower it and stores start rate-limiting you.

## `respectRobots` (type: `boolean`):

Stop if robots.txt disallows the endpoint. Keep this on.

## Actor input object example

```json
{
  "stores": [
    "salla.sa/coffee_souq",
    "otor200sa.com"
  ],
  "maxProductsPerStore": 1000,
  "onlyOnSale": false,
  "requestDelayMs": 200,
  "respectRobots": true
}
```

# Actor output Schema

## `results` (type: `string`):

Every product row.

## `runReport` (type: `string`):

Cost per 1,000 rows, stores reached, and the publish verdict.

# 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 = {
    "stores": [
        "salla.sa/coffee_souq",
        "otor200sa.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("abdulwhab95/salla-catalog-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 = { "stores": [
        "salla.sa/coffee_souq",
        "otor200sa.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("abdulwhab95/salla-catalog-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 '{
  "stores": [
    "salla.sa/coffee_souq",
    "otor200sa.com"
  ]
}' |
apify call abdulwhab95/salla-catalog-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,abdulwhab95/salla-catalog-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/ABcDcvTPvTao7a6pV/builds/1pYlO20V6WIwkHjfj/openapi.json
