Kaspi.kz Products Scraper
Pricing
from $1.75 / 1,000 results
Kaspi.kz Products Scraper
Products from Kaspi.kz, Kazakhstan's largest marketplace: price, bonus price, installments, merchants, rating and per-city delivery. The city is validated against Kaspi's own list of 320 first -- an unknown one is answered by Almaty, not by an error.
Pricing
from $1.75 / 1,000 results
Rating
0.0
(0)
Developer
Ibnu Adzim
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
6 days ago
Last modified
Categories
Share
Products from Kaspi.kz, Kazakhstan's dominant marketplace: price, sale price, the loyalty-bonus price, monthly installment terms, the merchants selling it, rating and review count, and the delivery window for the city you ask about.
Built on the storefront's own JSON search. HTTP only, no browser, no key.
What it is for
- Price monitoring in a market Amazon and AliExpress do not cover.
- Assortment research — what is listed, by whom, at what price.
- Merchant intelligence — every row carries the sellers and how many there are.
- Credit-terms analysis — Kaspi sells on installments, and the monthly figure is a first-class field.
Input
| field | what it does |
|---|---|
searchTerms | What to search for — iphone 15, ноутбук, холодильник. |
city | Slug, Russian name, English name or numeric id. Default: Almaty. |
onlyDiscounted | Keep only products whose sale price is below list. |
includePromoted | Add sponsored placements, flagged with isPromoted. |
maxItems, maxConcurrency, minRequestInterval | Limits and pacing. |
Four things about this data worth knowing
1. Three ways to ask for a city are accepted. One works.
X-KS-City is the header Kaspi's own front end sends and the one every
write-up reaches for. On this endpoint it does nothing. Measured on one
query, reading back the delivery windows:
| how the city was sent | delivery windows returned |
|---|---|
| not sent at all | EXPRESS |
header X-KS-City: 750000000 | EXPRESS — no change |
?cityId=710000000 | EXPRESS — ignored |
?c=999999999 (a city that does not exist) | EXPRESS — falls back to Almaty |
?c=710000000 (Astana) | EXPRESS, TODAY, TOMORROW ✓ |
?c=511010000 (Shymkent) | EXPRESS, TILL_2_DAYS, TILL_5_DAYS, TOMORROW ✓ |
All six return HTTP 200 with twelve real products. Nothing in the response says which city served it.
So this Actor sends c=, and checks your city against Kaspi's own list of 320
first — an unknown one stops the run rather than quietly returning Almaty.
2. The capital has three names and the one you would type is neither
Kaspi's own record for Astana is:
id 710000000 slug "nur-sultan" name "Астана" English "Astana"
The slug is still the city's former name, the name field is Cyrillic, and
astana matches neither. All four spellings resolve here.
3. The city always changes delivery. It changes some prices too.
The first measurement for this Actor compared the top 12 results across four cities, found every price identical, and concluded prices were national. A wider sample disproved it:
| query "iphone 15", 48 products per city, vs Almaty | prices differing |
|---|---|
| Astana | 5 / 48 (10.4%) |
| Shymkent | 4 / 48 (8.3%) |
| Atyrau | 3 / 48 (6.2%) |
Most gaps are trivial — 538,833 vs 538,868 ₸ — but not all: 567,309 vs 543,138 ₸ is a 24,000 ₸ difference on the same product id.
So the Actor makes no claim about this in its output. It reports the delivery windows it actually saw, which is the evidence your city took effect, and leaves the prices to speak for themselves.
4. There is no result count, and an empty search is a firehose
The response body is exactly
{"data": [...], "promotedCards": …, "promotedItems": …}matchCountAvailable: false says so
outright.
And the two ways a search can go wrong are asymmetric:
text=zzqqxxnotarealproduct -> 200, 0 products honesttext= -> 200, 12 products a generic catalogueno text parameter at all -> 200, 12 products the same generic page
The dangerous one is the second: it returns a page that looks like a working run. An empty term is refused before it is sent.
Output
PRODUCT—title,brand,price,salePrice,priceMinusBonus(the loyalty price, kept separate from the shelf price),creditMonthlyPrice,installmentMonths,rating,reviewsQuantity,merchants[],deliveryDuration,images[],productUrl,isPromoted.SEARCH_SUMMARY—productsReturned,matchCountAvailable: false,deliveryWindowsSeen,keywordMatchShare,duplicateRowsDropped,ceilingHit,stoppedReason.ERROR— one row naming what went wrong, instead of a silent empty.
Technical notes
- The proxy is ON by default, and it needs to be. Kaspi does not challenge a plain residential IP at all — five TLS profiles were clean cold. It does answer HTTP 429 to the address an Apify run egresses from directly: a cloud run with no proxy failed all four attempts on every request, while the identical code from a residential IP succeeded first time. Apify's free datacenter proxy clears it completely, so the default costs nothing. This is a property of Apify's egress, not of datacenter IPs in general — no need to reach for residential and its per-gigabyte bill.
- The city list has a built-in fallback. The storefront HTML is rate-limited
harder than the JSON, so even through the proxy it sometimes 429s. The city
guard matters more than its freshness, so a failed live read degrades to a
320-city snapshot taken 2026-09-16 and the summary says which was used
(
cityListSource). A city added since then would be refused. - The keyword check reads the category, not just the title. On Kaspi a
Russian search returns Latin-named products —
ноутбукgivesIndustria NT107 15.6" / 16 Гб / SSD 512 Гб. The Russian word is in the category path (Ноутбуки), sokeywordMatchSharematches across title, brand and category together. A title-only check scored a perfectly good 48-row search 0.0. - HTTP-only,
curl_cffichrome124. No WAF, no cookie, no key. The endpoint needs aRefereron the kaspi.kz origin; nothing else. - Paging stops at page 300. Page 301 is an HTTP 400 whose body names
nothing (
{"status":400,"error":"Bad Request","path":"/pl/results"}), so the wall is checked before the request rather than discovered by hitting it. At 12 products per page that is about 3,600 per search term. - Adjacent pages overlap — Kaspi re-ranks live, and pages 0 and 1 shared 2
of 12 ids in one measurement. Ids are deduplicated and the collisions counted
in
duplicateRowsDropped, so row counts are item counts. - Sponsored placements arrive in their own response keys rather than mixed into the results, which is unusually honest of Kaspi. They are still excluded by default and flagged when included.
- robots.txt checked on 2026-09-16: no AI-bot group, no blanket disallow, and both paths this Actor reads are allowed.
Known limits
- Kazakhstan only, prices in tenge.
- No match count, by construction — see above.
- ~3,600 products per search term. Slice by narrower terms to go wider.
- Product detail pages are not read; everything here comes from the search result card, which is already rich.