# Namshi, Extra, Nahdi & Centrepoint Scraper (`gulfprices/saudi-uae-marketplace-scraper`) Actor

Scrape product names, prices, stock and sellers from 8 Gulf online stores: Namshi, Extra, Nahdi, Centrepoint, Home Centre, Babyshop, Splash and Max Fashion. 36 storefronts across Saudi Arabia, UAE, Qatar, Kuwait, Oman and Bahrain, English or Arabic, for price monitoring and competitor tracking.

- **URL**: https://apify.com/gulfprices/saudi-uae-marketplace-scraper.md
- **Developed by:** [Gulf Prices](https://apify.com/gulfprices) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 products

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

Scrape **product names, prices, stock and sellers** from eight Gulf online stores, in
English or Arabic, returned as clean rows. Saudi Arabia and the UAE throughout, plus
Qatar, Kuwait, Oman and Bahrain on Namshi.

Most scraping tools skip this region. Whether you want a **Namshi scraper**, an
**Extra.com scraper**, or price data from **Nahdi**, **Centrepoint**, **Home
Centre**, **Babyshop**, **Splash** and **Max Fashion**, this is one Actor instead of
eight.

Built for **price monitoring**, **competitor tracking** and **Gulf market research**,
and for anyone assembling Middle East retail data for analysis or an AI pipeline.

> **Unofficial.** This Actor is not affiliated with, sponsored by or endorsed by
> Namshi, Extra, Nahdi, Centrepoint, Home Centre, Babyshop, Splash, Max Fashion or
> the Landmark Group. All product names and brands are the property of their
> owners, and are used here only to say which public store pages the Actor reads.

### 🏬 Which Gulf stores can you scrape?

Each store is available in the countries and languages it actually publishes, which
is 36 storefronts in total. The country sets the currency and the catalogue. The
language sets the product names, so Arabic storefronts return Arabic titles.

| Store | Countries | Languages | Category |
|---|---|---|---|
| **extra.com** | Saudi Arabia (SAR) | English, العربية | Electronics, appliances, home |
| **nahdionline.com** | Saudi Arabia (SAR) | English, العربية | Pharmacy, beauty, personal care |
| **namshi.com** | UAE (AED), Saudi Arabia (SAR), Qatar (QAR), Kuwait (KWD), Oman (OMR), Bahrain (BHD) | English, العربية | Fashion, footwear, beauty |
| **centrepointstores.com** | UAE (AED), Saudi Arabia (SAR) | English, العربية | Fashion, kids, home |
| **homecentre.com** | UAE (AED), Saudi Arabia (SAR) | English, العربية | Furniture, home decor |
| **babyshopstores.com** | UAE (AED), Saudi Arabia (SAR) | English, العربية | Baby, kids, nursery |
| **splashfashions.com** | UAE (AED), Saudi Arabia (SAR) | English, العربية | Fashion |
| **maxfashion.com** | UAE (AED), Saudi Arabia (SAR) | English, العربية | Value fashion, beauty |

### 📦 What data can you extract?

```json
{
  "source": "extra",
  "country": "sa",
  "language": "en",
  "name": "Panasonic Vacuum Cleaner 6L Dust Bag 1900W",
  "brand": "Panasonic",
  "sku": "100324003",
  "price": 1389.0,
  "currency": "SAR",
  "availability": "https://schema.org/InStock",
  "in_stock": true,
  "seller": "Extra Stores",
  "mpn": "MC-CG520",
  "image": "https://…",
  "url": "https://www.extra.com/en-sa/…",
  "fetched_at": "2026-08-30T12:57:41Z"
}
```

### 🚀 How to scrape Saudi and UAE stores

1. Pick a store from the **Store** dropdown. Each entry shows its country, language and currency.
2. Leave **Product URLs** empty to have the Actor find products for you, or paste
   product page URLs to watch a specific set.
3. Optionally set **Filter by keyword** to narrow what it finds, like `dress` or
   `perfume`.
4. Set **Max products** if you are discovering. It does not limit URLs you paste.
5. Press **Start**. Rows appear as they are collected, so a long run leaves results
   behind even if you stop it early.
6. Export from the **Output** tab as JSON, CSV or Excel, or pull the same rows from
   the API.

### ⚙️ Input

| Field | Description |
|---|---|
| **Store** | Pick one of the 36 storefronts. Each entry names its country, language and currency, so you can see what you are getting before you run it. |
| **Product URLs** | Specific pages to scrape. Leave empty to discover automatically. |
| **Filter by keyword** | Optional. Only collect products whose URL contains this word, such as `dress`, `perfume` or `adidas`. |
| **Max products** | How many to collect when discovering (default 20). Does not limit Product URLs you supply. |
| **Delay between requests** | Politeness delay in seconds (default 1). Under **Advanced**. |
| **Proxy** | Required for the storefronts marked **needs regional proxy**. Paste your own proxy endpoint in that country under **Own proxies**. Under **Advanced**. |

Supply your own product URLs to monitor a known set of SKUs, or leave it empty and
the Actor walks the store's own sitemap.

### 🛡️ Why this one keeps working

**It parses schema.org JSON-LD, not CSS selectors.** Marketplaces maintain their
JSON-LD carefully because Google's rich results depend on it, so it stays stable
across redesigns that break selector-based scrapers. Most scraper breakage is a class
name change; this Actor doesn't read class names.

**Every response is classified before parsing.** A blocked page that returns
`200 OK` is detected and reported rather than silently written to your dataset as an
empty row.

**Incomplete rows are dropped, not shipped.** A product without a name or price never
reaches your dataset. You will see fewer rows rather than wrong ones.

**Requests are paced and robots.txt is respected.** The one-second default was
measured against these stores rather than guessed, and you can raise it under
**Advanced** if a run ever does come back blocked.

### 🌍 Scraping Centrepoint, Home Centre, Babyshop, Splash and Max Fashion

Namshi, Extra and Nahdi work from anywhere. **Centrepoint, Home Centre, Babyshop,
Splash and Max Fashion serve their own region only**, and will return nothing from a
datacenter address or a proxy in the wrong country.

They are marked **needs regional proxy** in the Store dropdown. For those, open
**Advanced** and set **Proxy**.

Open **Advanced**, set **Proxy** to **Residential**, and press Start. The country is
chosen for you from the storefront you picked. You can paste your own endpoint under
**Own proxies** instead if you have a provider, but you do not need one.

These are also the cheapest stores here to collect: their category pages carry full
product data, so one request returns up to 48 priced products rather than one. A
thirty-product run takes about six seconds against a minute elsewhere, and it moves
roughly a fifteenth of the data the same products would cost one page at a time,
measured live.

If you do not have a proxy provider, **Namshi, Extra and Nahdi need no proxy at
all** and cover Saudi Arabia, the UAE, Qatar, Kuwait, Oman and Bahrain between them.
Residential is not offered for those three, because it would cost you reach they
already have.

### 💰 How much does it cost to scrape Namshi, Extra or Nahdi?

**$2.00 per 1,000 products.** That is a fifth of a cent per product, so a run that
returns 250 products costs 50 cents, plus five hundredths of a cent to start the
run. Platform usage is not billed on top of that: the compute, the bandwidth and the
proxies are ours, not yours.

**You are charged as each row lands in your dataset**, which means you pay for what
you actually receive. A page that fails, a product the store has stopped selling, a
run that matches your keyword nowhere: none of them add anything to the bill beyond
the run's own $0.00005 start. The same product reached from two different categories
is delivered once and charged once.

**Pasting Product URLs is faster than letting the Actor find them.** Discovery walks
the store's sitemap first, a few seconds before the first product is collected.
Pasting URLs skips straight to fetching. It costs the same either way, so this is
about how long you wait. If you are monitoring the same products on a schedule, which
is what most price tracking looks like, paste the URLs once and every later run
starts immediately.

A polite delay of one second per request is the other half of the runtime. It is
deliberate, and it is set where these stores were measured to be comfortable: 110
requests a second apart across Extra and Namshi produced no block, and none of the
eight publishes a Crawl-delay asking for more. You can raise it under **Advanced** if
a run does come back blocked, and the run summary tells you when that happens.

### 🔄 Scheduling, API and integrations

Everything the platform offers works here, and none of it needs extra setup:

- **Schedule** runs hourly, daily or weekly to build price history over time.
- **Monitor** runs and get alerted when one fails.
- **Call it from the API** in any language, or from the CLI.
- **Integrate** with Google Sheets, Slack, Zapier, Make, or your own webhook, so new
  rows land where you already work.
- **Export** as JSON, CSV, Excel or XML.

### ❓ FAQ

#### Is scraping these sites legal?

This Actor only collects publicly visible product information, the same data any
shopper sees without logging in. It reads each site's robots.txt and stays on the
paths those files permit. It collects no personal data. You are responsible for how
you use what you collect, and for the terms of the site you point it at.

#### Why is the seller empty on some stores?

Extra and Nahdi are true marketplaces: third parties sell through them, so they
publish who is selling each item and you get that in the `seller` column. The six
fashion stores are single-seller, so there is nothing to report and the field is left
empty rather than guessed.

#### Why is there no barcode or GTIN?

No Gulf store tested publishes one. The field is kept in the output so that if a
site ever starts, you get it automatically, but today it is empty everywhere.

#### It returned fewer products than I asked for.

Either the store delisted some pages, which shows in the log as delisted, or it
blocked part of the run, which shows as blocked with the reason. The run summary always
says which, so you never have to guess whether the Actor broke or the catalogue changed.

#### Can I search for a specific product?

Use **Filter by keyword**. On the stores collected from category pages it first finds
the categories whose name carries your word, so `stroller` goes straight to the five
stroller categories out of Centrepoint's 1,327 rather than sampling the catalogue and
hoping. If no category is named for your word it falls back to searching product
names and URLs, since the word may still appear inside a category not named for it.

`dress`, `perfume`, `stroller` and `adidas` all work well. Prefer a whole word where
you can, and paste Product URLs when you already know exactly which items you want.

#### Does this scrape Noon or Amazon.sa?

Not today, and it is worth saying why rather than leaving you to find out. Both serve
a bot challenge to plain HTTP requests, so collecting them needs a real browser, which
is roughly fifty times the cost per product and twenty times the wait. The eight
stores here all publish clean structured data that a plain request can read, which is
what keeps this fast and cheap. If Noon matters to you, say so on the issues page and
it will weigh on whether a browser-backed version is worth building.

#### Can you add another store?

Yes. Open an issue on the Actor and say which one.

### ⚠️ Notes and limits

- **To match a product across two stores**, use `brand` + `name` and expect to review
  the results. There is no barcode to join on, as above.
- **Prices are per store and per country.** The storefront you pick decides the
  currency, and the row records which country it came from.
- Noon, Jarir and Amazon.sa are **not** supported. Noon requires browser rendering
  plus rotating residential IPs; Jarir's sitemaps are broken on their side; Amazon
  disallows offer-listing pages in robots.txt. Message us if you need these, they
  are on the roadmap as a premium tier.

### 💬 Support

Open an issue on the Actor page. Bug reports that include the failing URL get fixed
fastest.

# Actor input Schema

## `source` (type: `string`):

Which store to collect from. The country sets the currency and the catalogue; the language sets the product names. Entries marked "needs regional proxy" only serve their own country, so set Proxy under Advanced to Residential before running one.

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

Specific product pages to scrape. Leave this empty and the Actor will find products on its own.

## `keyword` (type: `string`):

Optional. Only collect products whose URL contains this word, for example dress, perfume or adidas. Works well for categories and brand names. Short words can match inside longer ones, so prefer a whole word. Ignored when you supply Product URLs.

## `maxItems` (type: `integer`):

How many products to collect when the Actor is finding them itself. This does not limit Product URLs you supply, so paste as many as you like.

## `minIntervalSeconds` (type: `integer`):

Seconds to wait between requests. One is the default and was measured against these stores: 110 requests a second apart across Extra and Namshi produced no block, and none of the eight declares a Crawl-delay. Raise it if a run does start coming back blocked, which the run summary tells you.

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

The stores marked "needs regional proxy" only serve their own country: pick Residential and the country is chosen for you, or paste your own endpoint under Own proxies. Namshi, Extra and Nahdi need no proxy, and Residential is not offered for them. Google SERP and Unblocker are never supported.

## Actor input object example

```json
{
  "source": "extra-sa-en",
  "startUrls": [],
  "maxItems": 20,
  "minIntervalSeconds": 1,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

All collected product rows, in the order they were scraped.

## `productsCsv` (type: `string`):

The same rows as a spreadsheet-ready CSV.

# 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 = {
    "source": "extra-sa-en",
    "keyword": "",
    "maxItems": 20,
    "minIntervalSeconds": 1
};

// Run the Actor and wait for it to finish
const run = await client.actor("gulfprices/saudi-uae-marketplace-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 = {
    "source": "extra-sa-en",
    "keyword": "",
    "maxItems": 20,
    "minIntervalSeconds": 1,
}

# Run the Actor and wait for it to finish
run = client.actor("gulfprices/saudi-uae-marketplace-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 '{
  "source": "extra-sa-en",
  "keyword": "",
  "maxItems": 20,
  "minIntervalSeconds": 1
}' |
apify call gulfprices/saudi-uae-marketplace-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,gulfprices/saudi-uae-marketplace-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/R6eet5O5qIKsMZoQA/builds/mxYT6iVATEExMNogj/openapi.json
