# ikas Store Scraper | Products, Prices & Stock (`atesen-software/ikas-store-scraper`) Actor

Give an ikas store domain and get the catalogue: prices, discounts, stock, variants, SKUs, barcodes and images. Built for Turkish ecommerce price and stock monitoring. Changes-only mode returns new, changed and removed products.

- **URL**: https://apify.com/atesen-software/ikas-store-scraper.md
- **Developed by:** [Atesen Software](https://apify.com/atesen-software) (community)
- **Categories:** E-commerce, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.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?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

Scrape **any online store built on [ikas](https://ikas.com)**, the e-commerce platform behind about 20,000 Turkish shops. Give it a domain like `lepoleoutfit.com` and get the whole catalogue as JSON, CSV or Excel: **prices, discounts, stock, variants (size/colour), SKUs, barcodes, categories, ratings and images**. For **price & stock monitoring**, turn on *changes only* and schedule it to get just the new, changed and removed products.

- Works on every ikas storefront. The scraper finds products through the store's sitemap and reads the product data ikas embeds in each page.
- **No browser, no proxy.** It is fast and cheap.
- Checks that each site really runs on ikas. Other sites return a free `not_ikas` status row.

### Use cases

- **Competitor price monitoring** for D2C brands on ikas (schedule it daily or weekly).
- **Stock and assortment tracking**: new products, sold-out variants, discounts.
- **Catalogue export / migration** from an ikas store (with SKU and barcode).
- **Market research** across many Turkish D2C shops.

### How do I know a store runs on ikas?

ikas stores load images from `cdn.myikas.com`, and unbranded ones live on `*.ikas.shop`. You don't have to check yourself: put any domain in and the scraper tells you.

### Input

| Field | Description |
|---|---|
| `stores` | Store domains or URLs (`lepoleoutfit.com`, `https://www.shop.com`, `shop.ikas.shop`) |
| `productUrls` | Individual product URLs, to track specific products |
| `maxProductsPerStore` | Default 100; `0` = whole catalogue |
| `includeDescription` | Add the product description (plain text) |
| `maxConcurrency` | Parallel page loads per store (default 3) |
| `changesOnly` | Off by default. On: save only new, changed and removed products since the previous run; unchanged ones are free (see [Price & stock monitoring](#price--stock-monitoring)) |
| `monitorKey` | Optional name of the watch list; empty = derived from the input |

```json
{
  "stores": ["lepoleoutfit.com", "pastirmacipolat.com"],
  "maxProductsPerStore": 100
}
```

### Output

One row per product. Variants are nested:

```json
{
  "type": "product",
  "store": "pastirmacipolat.com",
  "productId": "9dd6875b-f8a0-40f8-bad9-c5b5a5e35946",
  "name": "Kayseri Sucuğu",
  "brand": "Pastırmacı Polat",
  "url": "https://pastirmacipolat.com/kayseri-sucugu",
  "price": 675,
  "originalPrice": null,
  "discountPercent": null,
  "currency": "TRY",
  "minPrice": 675,
  "maxPrice": 6750,
  "inStock": true,
  "totalStock": 60,
  "sku": null,
  "barcode": null,
  "categories": ["Kayseri Sucuğu"],
  "rating": 4.77,
  "reviewCount": 154,
  "imageUrl": "https://cdn.myikas.com/images/.../image_1080.webp",
  "variantCount": 6,
  "variants": [
    { "variantId": "3602eb28-...", "sku": null, "barcodes": [], "options": { "Kilogram": "500gr" }, "price": 675, "originalPrice": null, "stock": 10, "inStock": true }
  ]
}
```

`price` is the current selling price (campaign or discounted price when there is one). `originalPrice` is the crossed-out list price. Stock numbers are the ones the store publishes on its product pages.

#### Status rows

The run doesn't fail on bad input. Problems become rows with `type: "status"` and are **never charged**:

| status | meaning |
|---|---|
| `invalid_input` | No stores or product URLs given |
| `invalid_url` | Not a valid domain or URL |
| `unreachable` / `failed` | The site could not be loaded |
| `not_ikas` | The site or page does not run on ikas |
| `no_products` | The store's sitemap lists no live products |
| `not_found` | A product URL returned 404 |
| `not_a_product` | An ikas page that is not a product page |

Removed products that are still listed in a store's sitemap are skipped automatically and not charged. `RUN_SUMMARY` in the key-value store has counts.

### Price & stock monitoring

Turn on **Changes only** (`changesOnly: true`) and schedule the Actor. Each run is compared with the previous run of the same input (or the same **Monitor name**, `monitorKey`), and only what changed is saved. Unchanged products are **not saved and not charged**; new and changed products cost the normal per-product price.

| `changeType` | Meaning | Charged |
| --- | --- | --- |
| `new` | first time this product is seen (every product on the first run) | yes, as a normal product |
| `price_changed` | price went up or down, also per variant (`previousPrice`, `priceChange`, `priceChangePercent`) | yes |
| `unavailable` | still listed but sold out — temporarily unavailable | yes |
| `back_in_stock` | sold out last time, buyable again | yes |
| `stock_changed` | stock quantity changed, or a variant sold out / came back | yes |
| `variants_changed` | a variant (size, colour) was added or removed | yes |
| `removed` | product is gone: its page returns 404 (`removedReason: not_found`), or it was missing from the store's sitemap or a fully crawled store two runs in a row (`not_listed`) | **free** |
| unchanged | not saved | **free** |

Every changed row keeps all the normal product fields and adds `changeType`, a `changes` list (e.g. `{"field": "price", "from": 1299, "to": 1149}`), `previousPrice`, `priceChange`, `priceChangePercent`, `previousInStock`, `previousSeenAt` and `firstSeenAt`. Products are matched by store + the platform's stable product ID (`productId`; variants by `variantId`), so a renamed product is not reported as new. A product that could not be loaded in one run (timeout, block) is never reported as removed. The **Changes** view in the Output tab shows just these columns; the run summary (`RUN_SUMMARY`) counts new, changed, unchanged and removed products.

Schedule example — every morning, get only the price and stock changes:

```json
{
  "stores": ["lepoleoutfit.com"],
  "maxProductsPerStore": 0,
  "changesOnly": true,
  "monitorKey": "lepoleoutfit-daily"
}
```

Save the input as a task, then in Apify Console open **Schedules → Create new**, set cron `0 7 * * *` (07:00 every day) and add the task. Connect a webhook, Google Sheets or Slack integration to receive only the changes. Use `maxProductsPerStore: 0` (whole store) for complete removal detection; with a limit, the same first products of the sitemap are compared. Keep the input the same between runs: a different input or monitor name starts a new watch list (all products `new` again).

### Pricing

**$0.001 per product** (pay per event, $1 per 1,000 products). Status rows are free. Set a maximum cost per run and the scraper stops cleanly when it is reached.

### Related actors

- [Trendyol Scraper](https://apify.com/atesen-software/trendyol-scraper)
- [Hepsiburada Scraper](https://apify.com/atesen-software/hepsiburada-scraper)
- [Trendyol Reviews Scraper](https://apify.com/atesen-software/trendyol-reviews-scraper)

### Notes

Only public product information is collected: no customer data, no login, no checkout. Use the data responsibly and follow each store's terms and applicable law. This actor is not affiliated with ikas.

### FAQ

**Which stores work?** Public ikas storefronts. Paste the domain. A store that is not ikas, or that blocks the request, becomes a free status row.

**How do I monitor price and stock?** Turn on `changesOnly` and reuse the same `monitorKey`.

**What does the first run return?** The saved example reads two real ikas stores and returns product rows (name, price, stock, SKU, URL). It does not crawl the whole catalogue unless you raise the limit.

# Actor input Schema

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

Domains or URLs of stores running on ikas, e.g. "lepoleoutfit.com" or "https://www.mystore.com" or "mystore.ikas.shop". The scraper checks that the site is an ikas store, reads its product sitemap and scrapes every product page.

## `productUrls` (type: `array`):

Individual product page URLs from any ikas store. Use this to track prices of specific products.

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

Stop after this many products for each store. 0 = the whole catalogue.

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

Add the product description as plain text.

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

How many product pages are loaded at the same time. Keep it low to be gentle with small shops.

## `changesOnly` (type: `boolean`):

Compare every product with the previous run that used the same input (or the same monitor name) and write only **new** products and products whose **price or stock changed** (each row gets a changeType: new, price_changed, stock_changed, variants_changed, unavailable, back_in_stock). Products that disappeared are written as free 'removed' rows. Unchanged products are skipped and not charged. Off (default) = normal full scrape. Schedule the Actor with this on to get a daily change feed.

## `monitorKey` (type: `string`):

Optional. Runs with the same name share one snapshot. Leave empty to derive it automatically from your store domains and product URLs, so the same input always continues the same watch list.

## Actor input object example

```json
{
  "stores": [
    "lepoleoutfit.com",
    "pastirmacipolat.com"
  ],
  "maxProductsPerStore": 100,
  "includeDescription": false,
  "maxConcurrency": 3,
  "changesOnly": false
}
```

# Actor output Schema

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

No description

## `changes` (type: `string`):

No description

## `allFields` (type: `string`):

No description

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

No description

# 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": [
        "lepoleoutfit.com",
        "pastirmacipolat.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("atesen-software/ikas-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 = { "stores": [
        "lepoleoutfit.com",
        "pastirmacipolat.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("atesen-software/ikas-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 '{
  "stores": [
    "lepoleoutfit.com",
    "pastirmacipolat.com"
  ]
}' |
apify call atesen-software/ikas-store-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,atesen-software/ikas-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/VV2wgAL2oG9yJebvb/builds/xHZvnEtQArz56HZfN/openapi.json
