# Salla & Zid Store Scraper (سلة / زد) (`almoutasem_nabil/salla-zid-store-scraper`) Actor

Extract the full product catalog (prices, stock, variants, images) from any online store built on Salla or Zid, the leading e-commerce platforms in Saudi Arabia and the Gulf. Auto-detects the platform.

- **URL**: https://apify.com/almoutasem\_nabil/salla-zid-store-scraper.md
- **Developed by:** [Al Moutasem Nabil](https://apify.com/almoutasem_nabil) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 product 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?

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 & Zid Store Scraper (سلة / زد)

**Extract the complete product catalog of any online store built on [Salla](https://salla.sa) or [Zid](https://zid.sa), the two platforms that power most e-commerce in Saudi Arabia and the Gulf.**

Give it a list of store homepages. The Actor detects whether each store runs on Salla (متجر سلة) or Zid (متجر زد), discovers every product, and returns one clean JSON record per product with price, price before discount, stock, variants, images, categories, rating and more. No selectors to configure, no platform to choose, no JavaScript rendering needed.

### What you get

- **Auto-detection** of the platform from the homepage (custom domains, `salla.sa/<slug>` paths and `*.zid.store` subdomains all work).
- **Complete catalogs** via the most reliable discovery path for each platform: Salla's public storefront API, Zid's product sitemap, with automatic fallbacks (sitemap for Salla, listing pagination for Zid).
- **Structured prices**: current price, regular price before discount, discount percentage, currency.
- **Stock**: in-stock flag and the exact quantity when the store exposes it.
- **Variants** (sizes, colors, lengths...) with their own price, SKU and availability.
- **Images**, categories, brand, rating and review count.
- **Per-store isolation**: one broken or closed store never fails the run; a summary of every store is stored in the key-value store as `SUMMARY`.
- **Deduplication** by product URL, retries, polite default concurrency.
- **No personal data**: reviewer names, customer names, phone numbers and emails are never collected.

### Who is it for?

- **Price monitoring** of competitors or your own resellers across متاجر إلكترونية in KSA and the GCC.
- **Brand owners** checking which resellers list their products, at which price and whether they honor MAP.
- **Market research** on assortment, pricing and discount depth in categories like fashion, perfumes, cosmetics, electronics and home goods.
- **Lead generation**: qualify Saudi e-commerce stores by catalog size, price range and categories before reaching out.
- **Data teams** feeding product feeds into BI tools, spreadsheets or LLM pipelines.

### Input

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `storeUrls` | array of URLs | required | Store homepages, one per line. |
| `maxProductsPerStore` | integer | `0` (unlimited) | Stop after this many products per store. |
| `includeVariants` | boolean | `true` | Extract variants (sizes, colors...) with price, SKU and stock. |
| `includeOutOfStock` | boolean | `true` | Keep sold-out products. |
| `includeDescription` | boolean | `false` | Add the plain-text description (large). |
| `proxyConfiguration` | object | Apify datacenter proxy | Datacenter proxies are enough for both platforms. |
| `maxConcurrency` | integer | `5` | Parallel requests across all stores. Keep it low for small shops. |

Example input:

```json
{
    "storeUrls": ["https://parispolly.com", "https://salla.sa/hnperfume", "https://bkor268.zid.store", "https://alamirah-sa.zid.store"],
    "maxProductsPerStore": 0,
    "includeVariants": true,
    "includeOutOfStock": true,
    "includeDescription": false,
    "maxConcurrency": 5
}
```

### Output

One dataset item per product. This is a real record scraped from a Zid abaya store:

```json
{
    "storeName": "مؤسسة الأميرة للعبايات للتجارة",
    "storeUrl": "https://alamirah-sa.zid.store",
    "platform": "zid",
    "productId": "82b9f089-64fa-412c-9b84-6b0ff5a3a83a",
    "sku": "19004248",
    "name": "طقم النجوم كبك ثوب دبليو",
    "url": "https://alamirah-sa.zid.store/products/عبايات-كاجوال",
    "brand": null,
    "categories": ["عبايات سادة", "جميع العبايات"],
    "price": 165.6,
    "regularPrice": 276,
    "currency": "SAR",
    "discountPercent": 40,
    "inStock": true,
    "quantity": 138,
    "rating": 5,
    "reviewCount": 4,
    "images": [
        "https://media.zid.store/40c3728d-0357-45d1-9800-76ff522e15c3/ce485393-13f6-4025-a97f-fc2349a76d6f.jpeg",
        "https://media.zid.store/40c3728d-0357-45d1-9800-76ff522e15c3/001f6f10-e7ab-4b36-a224-070c6921f5d9.jpeg"
    ],
    "variants": [
        {
            "name": "طقم النجوم كبك ثوب دبليو - 44 - مسكر",
            "options": { "القفله": "مسكر", "المقاس": "44" },
            "price": 165.6,
            "sku": "Z.63654.1606136625233955437",
            "inStock": true
        },
        {
            "name": "طقم النجوم كبك ثوب دبليو - 44 - سحاب",
            "options": { "القفله": "سحاب", "المقاس": "44" },
            "price": 165.6,
            "sku": "Z.63654.1606136625233280736",
            "inStock": true
        }
    ],
    "scrapedAt": "2026-09-05T16:16:12.418Z"
}
```

And a Salla perfume store record:

```json
{
    "storeName": "متجر HN للعطور",
    "storeUrl": "https://salla.sa/hnperfume",
    "platform": "salla",
    "productId": "388030321",
    "sku": "HN-TEFANY1",
    "name": "عطر TEFANY",
    "url": "https://salla.sa/hnperfume/عطر-tefany/p388030321",
    "brand": null,
    "categories": ["العطور"],
    "price": 99,
    "regularPrice": 149,
    "currency": "SAR",
    "discountPercent": 34,
    "inStock": true,
    "quantity": null,
    "rating": 5,
    "reviewCount": 3,
    "images": ["https://cdn.salla.sa/qzbZe/a77bb53c-e380-4533-bd7a-0c6a439445da-500x500-NZ3oILWlCBD0VWXpNemhYb8lMTFozcK3xEi4c7bb.png"],
    "variants": [],
    "scrapedAt": "2026-09-05T16:16:07.102Z"
}
```

Field reference:

| Field | Description |
| --- | --- |
| `storeName`, `storeUrl`, `platform` | Store identity; `platform` is `"salla"` or `"zid"`. |
| `productId`, `sku`, `name`, `url` | Platform product id, merchant SKU, product title and canonical product URL. |
| `brand`, `categories` | Brand name (if the store uses brands) and category names. |
| `price`, `regularPrice`, `currency`, `discountPercent` | Current price, price before discount, ISO currency (usually `SAR`), rounded discount percentage (`0` when there is none). |
| `inStock`, `quantity` | Availability and remaining quantity when the store exposes it (`null` for unlimited or hidden stock). |
| `rating`, `reviewCount` | Average rating out of 5 and number of ratings, `null` when there are none. |
| `images` | Full-size image URLs, main image first. |
| `variants[]` | `{ name, options, price, sku, inStock }` per variant. |
| `description` | Plain-text description, only when `includeDescription` is on. |
| `scrapedAt` | ISO 8601 timestamp. |

The key-value store record `SUMMARY` lists every input store with its detected platform, discovery method, discovered / scraped counts, skipped and failed requests, and the error message for stores that could not be scraped.

### How to run

**Console**: paste the store URLs, click *Start*. Export the dataset as JSON, CSV or Excel from the *Output* tab.

**API** (replace `<token>` and the Actor id):

```bash
curl -X POST "https://api.apify.com/v2/acts/<username>~salla-zid-store-scraper/run-sync-get-dataset-items?token=<token>" \
  -H "Content-Type: application/json" \
  -d '{ "storeUrls": ["https://parispolly.com"], "maxProductsPerStore": 100 }'
```

**JavaScript client**:

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

const client = new ApifyClient({ token: '<token>' });
const run = await client.actor('<username>/salla-zid-store-scraper').call({
    storeUrls: ['https://parispolly.com', 'https://bkor268.zid.store'],
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

**Schedule**: open the Actor, click *Schedule*, pick a cadence (daily price monitoring is the common choice) and connect a webhook or an integration (Google Sheets, Slack, Make, Zapier) to the schedule so every run lands where your team works.

### Pricing

The Actor uses **pay-per-event** pricing. You only pay for what was actually delivered:

| Event | Price | When it is charged |
| --- | --- | --- |
| Store started | $0.01 | Once per input store whose platform was detected. Closed or unrecognised stores are free. |
| Product scraped | $0.003 | Once per unique product saved to the dataset. Skipped, duplicated and failed products are free. |

A store with 341 products costs about $1.03; ten stores with 5,000 products in total cost about $15. Set *Maximum total charge* on the run to cap spending; the Actor stops cleanly when the cap is reached and keeps everything scraped so far. Apify platform usage (compute) is billed separately according to your plan.

### FAQ

**How does the Actor know a store is on Salla or Zid?** It fetches the homepage once and looks for platform fingerprints: Salla's Twilight SDK and `<salla-*>` web components, Zid's asset CDN and store bootstrap variables. Custom domains work because the fingerprints are in the HTML, not the URL.

**How are products discovered?** Salla: the storefront's own public product API (the same one the theme calls in your browser), paginated to the end, with the sitemap as a fallback. Zid: `sitemap_products.xml`, with the `/products` listing as a fallback. Both paths are more robust than following category links.

**Do I get variant-level stock?** Yes on both platforms. Zid embeds every variant with its quantity; Salla exposes availability per option value.

**Why does a Salla product only have one image?** Salla's list API returns the main image. When `includeVariants` is on and the product has options, or when `includeDescription` is on, the product page is fetched and the full gallery is extracted.

**Can I limit cost on a huge store?** Use `maxProductsPerStore`, `includeOutOfStock: false`, or the run's *Maximum total charge*.

**Does it work on Salla stores with a `salla.sa/<slug>` URL?** Yes. Those stores hide their sitemap behind a Cloudflare challenge, but the API path does not need it.

**Arabic or English names?** Whatever the store publishes by default (Arabic for almost all stores). Multilingual stores return Arabic first.

### Limitations

- Product **descriptions** are returned as plain text, not HTML.
- **Rating** on Salla is only available when the store enables ratings; Zid ratings need at least one review.
- Stores that are **closed for maintenance**, password-protected or not on Salla/Zid are reported in `SUMMARY` and skipped.
- The Actor reads public storefront data only; it does not log in, does not see wholesale/B2B prices and does not read the platforms' merchant APIs.
- Prices are returned in the store's default currency (almost always SAR).

### Legal note

This Actor collects only publicly available product information that any visitor can see on the storefront. It honours `robots.txt` on both platforms (it never touches Zid's `/api/` or review pages), uses polite concurrency, and never stores personal data: no customer or reviewer names, phones, emails or addresses. You are responsible for using the data in line with the store's terms and the laws that apply to you (including the Saudi PDPL). Salla and Zid are trademarks of their respective owners; this Actor is not affiliated with either company.

### Keywords

Salla scraper, Zid scraper, Saudi e-commerce data, KSA product prices, سلة, زد, متجر إلكتروني, سكرابر سلة, بيانات المنتجات, مراقبة الأسعار, GCC price monitoring.

# Actor input Schema

## `storeUrls` (type: `array`):

Homepage URLs of the stores to scrape. Custom domains (https://brand.com), Salla paths (https://salla.sa/store-slug) and Zid subdomains (https://store.zid.store) all work. One store per line.

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

Stop after this many products have been saved for a store. Use 0 for no limit (the whole catalog).

## `includeVariants` (type: `boolean`):

Extract product variants (sizes, colors, ...) with their own price, SKU and stock status. On Salla this needs one extra request per product that has options.

## `includeOutOfStock` (type: `boolean`):

Keep products that are currently sold out. Turn off to only get products that can be bought right now.

## `includeDescription` (type: `boolean`):

Add the full product description (plain text) to every item. Off by default because descriptions are large and make the dataset heavier.

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

Proxies to use. Apify datacenter proxies are enough for Salla and Zid stores. Switch to residential proxies only if you see many blocked requests.

## `maxConcurrency` (type: `integer`):

Maximum number of pages fetched in parallel across all stores. Keep it low (3-5) to be polite to small shops; raise it for large catalogs.

## Actor input object example

```json
{
  "storeUrls": [
    "https://parispolly.com",
    "https://salla.sa/hnperfume",
    "https://bkor268.zid.store",
    "https://alamirah-sa.zid.store"
  ],
  "maxProductsPerStore": 0,
  "includeVariants": true,
  "includeOutOfStock": true,
  "includeDescription": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "maxConcurrency": 5
}
```

# Actor output Schema

## `products` (type: `string`):

One dataset item per product.

## `summary` (type: `string`):

Platform, discovery method and product counts for every store in the run.

# 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 = {
    "storeUrls": [
        "https://parispolly.com",
        "https://salla.sa/hnperfume",
        "https://bkor268.zid.store",
        "https://alamirah-sa.zid.store"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("almoutasem_nabil/salla-zid-store-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 = {
    "storeUrls": [
        "https://parispolly.com",
        "https://salla.sa/hnperfume",
        "https://bkor268.zid.store",
        "https://alamirah-sa.zid.store",
    ],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("almoutasem_nabil/salla-zid-store-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 '{
  "storeUrls": [
    "https://parispolly.com",
    "https://salla.sa/hnperfume",
    "https://bkor268.zid.store",
    "https://alamirah-sa.zid.store"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call almoutasem_nabil/salla-zid-store-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,almoutasem_nabil/salla-zid-store-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/mqAjiAzXe9We5b0ka/builds/87Uc09q9VSSrybE1N/openapi.json
