Salla Store Scraper — Products, Prices & Stock avatar

Salla Store Scraper — Products, Prices & Stock

Pricing

Pay per usage

Go to Apify Store
Salla Store Scraper — Products, Prices & Stock

Salla Store Scraper — Products, Prices & Stock

Read any Salla (سلة) store and get every public product as clean structured data — Arabic names intact, prices in SAR, live availability. تصدير منتجات سلة.

Pricing

Pay per usage

Rating

0.0

(0)

Developer

Hussein Al-Mansori

Hussein Al-Mansori

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

10 days ago

Last modified

Share

Salla Store Scraper — Products, Prices & Stock (سلة)

Paste any Salla store address and get its public catalogue back as clean, structured data — product names exactly as the store wrote them, prices in the store's own currency, and live availability.

متجر سلة → بيانات منتجات نظيفة. Salla (سلة) powers tens of thousands of Saudi online stores. This Actor reads them properly, in Arabic, without mangling a single character.

Who this is for

You areWhat you get
A merchant on SallaAn export or backup of your own catalogue, in a file you can actually reopen
A competing merchant or agencyCompetitor assortment and pricing across the Saudi market
A market researcherStructured MENA e-commerce data, one row per product

Exporting your own store is the case this was built for first. It is your catalogue, and Salla gives you no easy button for it.

What you paste in

A store home page, a category page, or a single product page — and you can mix them in one run. Both kinds of Salla address work:

  • a store on Salla's own domain, like https://salla.sa/your-store
  • a store on its own domain, like https://yourbrand.com

If an address is not a Salla store, the result says exactly that instead of returning nothing.

Input

FieldTypeDefaultWhat it does
startUrlslist of URLsThe stores, categories, or products to read. Required.
maxItemsinteger200Stop after this many products from each store.
includeOutOfStockbooleantrueKeep sold-out products. Turn off for buyable stock only.
includeVariantsbooleantrueList options as variants when the store publishes them.
languageauto / ar / enautoPreferred storefront language when a store has more than one.
respectRobotsbooleantrueSkip any address the store's robots.txt asks crawlers not to read. Checked on every page read, not just the first.
proxyConfigurationobjectoffLeave off unless a store refuses the connection — see below.

A run needs nothing but startUrls.

On proxies, and on currency. Two things worth knowing, both measured rather than assumed.

Salla sits behind a CDN that challenges data-centre addresses, so a data-centre proxy reaches fewer stores than no proxy at all — the same store read cleanly on a direct connection and came back as an unreadable challenge page through the data-centre proxy. Proxies are therefore off by default, and a residential proxy is the escalation if a store refuses the connection.

Some stores also localise by where the request comes from. One store returned 290 SAR read from Saudi Arabia and 105 USD read from a US data centre — a different currency and a different number, for the same product. Every row carries its own currency, so nothing is mislabelled, but if you need Saudi pricing specifically, run through a residential proxy pinned to Saudi Arabia:

{ "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"], "apifyProxyCountry": "SA" }

What you get back

Real output from a live run: product rows with Arabic and English names, prices, sale prices,
stock, and SKUs, plus one summary row per store

Two kinds of row, told apart by event. Everything above is real output from a live run — no sample data was written by hand.

One product-scraped row per product:

{
"event": "product-scraped",
"platform": "salla",
"store": { "name": "متجر النور", "domain": "salla.sa/alnoor", "id": "618430553" },
"url": "https://salla.sa/alnoor/abaya/p12345",
"nameAr": "عباية كاجوال قطن",
"nameEn": null,
"price": 149.0,
"salePrice": 119.0,
"currency": "SAR",
"availability": "in_stock",
"sku": "AB-1042",
"brand": null,
"categories": ["عبايات"],
"images": ["https://cdn.salla.sa/....jpg"],
"variants": [],
"hasOptions": false,
"scrapedAt": "2026-08-21T14:03:22Z",
"status": "verified"
}

One store-analyzed row per store, summarising what happened:

{
"event": "store-analyzed",
"platform": "salla",
"store": { "name": "متجر النور", "domain": "salla.sa/alnoor", "id": "618430553" },
"storeUrl": "https://salla.sa/alnoor",
"productsDiscovered": 412,
"productsScraped": 200,
"productsWithOptions": 18,
"pricesCrossChecked": 5,
"pricesDisagreed": 0,
"stoppedBy": "maxItems",
"discoveryMethod": "storefront-api",
"status": "warning",
"warnings": [{ "code": "ITEM_LIMIT_REACHED", "message": "…" }]
}

Every row stands on its own — a product row repeats the store it came from, so one row is enough to act on without joining it to anything.

Arabic, handled properly

Names come back in the script the store wrote them in. An Arabic name lands in nameAr and nameEn stays null; an English name does the reverse. Nothing is machine-translated, and no name is ever transliterated or stripped.

Downloading as CSV opens in Excel with Arabic intact — Apify prefixes CSV exports with a UTF-8 byte order mark, which is the thing Excel needs and the thing most exports forget.

How honest the row is

statusMeaning
verifiedRead cleanly. Nothing was uncertain.
warningDelivered, but something was uncertain — the reason is on the row.
failedNothing could be delivered. Never charged.

Three rules this Actor does not bend:

  • A field that could not be read is null. It is never guessed, never zero, and never a placeholder. If a store publishes no SKU, sku is null — even when the page offers something SKU-shaped that is really just part of the address.
  • Stock is only ever what the store said. A store that says nothing gets availability: "unknown", not "in_stock".
  • Some products are checked against the store's own product page. A sample from each store is read twice, from the store's catalogue and from the product's own page. When the two disagree about price or stock, the row keeps the catalogue value and stops calling itself verified — it carries PRICE_MISMATCH or AVAILABILITY_MISMATCH so you know that number is contested. It happens on real stores: one live catalogue lists a perfume as in stock that its own product page marks sold out. The store row publishes pricesCrossChecked and pricesDisagreed, so you can see the size of the check and not just its verdict.

Tested on 31 live Salla stores

Nobody else on the Store publishes numbers. These come from scripts/run_store_scorecard.py, run on 2026-08-22 against 31 live Salla storefronts and 855 products — sizes from 3 products to 600+, across perfume and oud, abayas, gifts, toys, dates and coffee, electronics, sportswear, supplements, pet supplies, stationery and collectibles. Eleven were read on the merchant's own domain and twenty on a salla.sa address.

Every figure below is a count from that run, not an estimate. Ask on the Actor's issues page if you want the store list to reproduce it.

FieldExtracted
Product name100%
Price100%
Availability100%
Images99.4%
Categories89.8%
SKU13.7%
Variants0%

Cross-check: 153 products were also read from their own product page. 11 disagreed — 92.8% agreement. Those 11 are the reason the check exists; each is flagged on its row rather than shipped as clean data.

Two of these numbers deserve their honest explanation rather than a flattering one:

  • SKU 13.7% is not a failure to extract. Most Salla merchants never set a SKU. When they haven't, Salla's product page fills the field with the product's own URL slug — and this Actor refuses to publish that as a SKU. A scraper that passed the slug through would show a far prettier number and hand you a column you cannot match against your own catalogue.
  • Variants 0%, and 26% of products have them. 220 of the 855 products told us they have options like colour or size. Salla does not publish the option values anywhere reachable without running the store's JavaScript, so this Actor does not invent them. Those products carry hasOptions: true so you know the variants exist and that we could not read them. Fixing this properly means adding a browser, which is a cost decision and not yet made.

Error codes

CodeMeaningRetry?
NOT_A_SALLA_STOREReachable, but not a Salla storeNo
ROBOTS_DISALLOWEDThe store's robots.txt asks crawlers not to read itNo
STORE_UNREACHABLEThe store could not be reachedYes
STORE_TIMEOUTThe store did not respond in timeYes
PRODUCT_PARSE_FAILEDA product address you submitted publishes no readable detailsNo
INVALID_URLThe address is not a usable http/https URLNo
BLOCKED_DESTINATIONThe address resolves somewhere requests are not sentNo
DNS_FAILUREThe hostname does not resolveNo
STORAGE_FAILUREThe result could not be saved. Never charged.Yes
BUDGET_EXHAUSTEDThe run's charge limit is spentNo
INTERNAL_ERRORSomething unexpected. Nothing internal is ever shown to you.Yes

A closed store is not an error. Salla stores can be switched off by their owner, and that is a real answer: the row comes back with stoppedBy: "storeClosed" and a STORE_CLOSED warning, naming the store, rather than pretending its catalogue is empty.

One unreadable product inside a catalogue is not an error either — it is left out, the rest are still returned, and the store row carries a PRODUCT_PARSE_FAILED warning saying so.

ROBOTS_DISALLOWED above stops a whole store. When robots.txt closes only some addresses, the run continues without them and the store row carries a ROBOTS_LIMITED_DISCOVERY warning saying how many were skipped — so a catalogue shortened by the store's own instruction never looks complete.

Limits

LimitValue
Stores per run50
Products per store5,000 (maxItems, default 200)
Time per store300 seconds
Stores read at once2
Images kept per product20
Variants kept per product50
Products cross-checked per store5

What this deliberately does not do

  • No reviews, no customer data, no store-owner contact details. Product data only.
  • No logged-in areas, carts, checkouts, or coupon probing. Public catalogue only.
  • No image downloading — URLs only.
  • No "search all of Salla": it reads the stores you name.

Pricing

Free. Only Apify's platform usage applies. Two events are defined — product-scraped (one per product) and store-analyzed (one per store per run) — and neither is charged today.

They exist so that adding a price later would be a price change and not a redesign. Nothing is planned.

Works well with

Website Change Monitor with Smart Diff — take a product address from this Actor and hand it to the monitor to be told when that price moves.

Zid Store Scraper — the same job for Zid (زد), Salla's main rival. Identical field names and identical values inside them, so the two datasets concatenate into one sheet with no renaming, and every row's platform says which shop it came from.


FAQ

Does it work on a store with its own domain? Yes. Eleven of the 31 stores in the scorecard were read on the merchant's own domain.

Does it need my store login? No. Public catalogue pages only. This Actor never touches logins, carts, checkout, or coupons.

Does it get reviews or customer data? No. Product data only.

Why is sku empty on so many rows? Because most Salla merchants never set one — 13.7% of the scorecard's products had a SKU at all. That is the store's choice, not a failed read, and an invented value would be worse than null.

Why are variants empty? Salla builds its option pickers in the browser, and this Actor reads the storefront API instead of running one. Rather than guess, it reports nothing and says so. See the scorecard.

Does language: ar translate the store? No. It says which language you expected; if the store does not publish it, the row carries a LANGUAGE_UNAVAILABLE warning and you get the store's own language. Nothing is machine-translated.

Does it download the images? No — you get URLs.

Does it scrape Zid stores? No. That is the separate Zid Store Scraper.

Can it find every Salla store for me? No. It reads the store URLs you give it.


Support

Open an issue on the Actor's Apify page. Include the run ID and the store URL — the store-analyzed row tells us most of what we need.

Not affiliated with, endorsed by, or sponsored by Salla (سلة).