# A101 Product Scraper | Fast & Reliable (`fatihtahta/a101-product-scraper`) Actor

Extract A101 product data at scale with pricing, availability, category paths, images, variants, badges, campaign collections, and A101 Ekstra/Kapında coverage. Built for enterprise-grade Turkish retail intelligence, assortment monitoring, and automated analytics pipelines.

- **URL**: https://apify.com/fatihtahta/a101-product-scraper.md
- **Developed by:** [Fatih Tahta](https://apify.com/fatihtahta) (community)
- **Categories:** E-commerce, Automation, Developer tools
- **Stats:** 3 total users, 1 monthly users, 89.7% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.70 / 1,000 product listings

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use 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

## A101 Product Scraper

**Slug:** `fatihtahta/a101-product-scraper`

### Overview

A101 Product Scraper collects structured product records from A101 search queries, A101 search result URLs, category URLs, and individual product URLs. Records include product identity, title, brand, category hierarchy, public product URL, pricing, availability, images, badges, variants, collection context, and source context when available. [A101](https://www.a101.com.tr/) is a major Turkish retail and e-commerce destination, making its public catalog useful for assortment analysis, price monitoring, product discovery, and reporting. The actor helps teams turn repeatable catalog collection into structured records that can be reviewed, exported, merged into existing systems, or monitored over time. It supports both A101 Ekstra and A101 Kapında catalog scopes, optional TRY price boundaries, bounded output volume, and richer product detail collection. Results are delivered as structured Apify dataset records suitable for review, export, analytics, AI-agent workflows, and downstream processing. The actor is designed for dependable recurring public catalog acquisition without making unsupported claims about full-market coverage, completeness, or service-level guarantees.

### Who Should Use This Actor

- **Market research and analytics teams:** monitor A101 assortment, price points, category movement, availability signals, and campaign positioning in a repeatable dataset.
- **Product and catalog teams:** enrich internal product catalogs with public product names, brand labels, category paths, image URLs, availability fields, and merchandising context.
- **E-commerce operations teams:** track selected categories, product families, price bands, and recurring catalog segments for operational reporting.
- **Developers and data engineering teams:** feed normalized product records into ETL jobs, warehouses, search indexes, dashboards, and internal data products.
- **AI agents and workflow automations:** collect scoped product datasets that can be summarized, compared, routed, or checked against downstream business rules.
- **Competitive intelligence teams:** compare public product availability, visible price changes, product groupings, badges, and category coverage across repeated runs.

### Common Use Cases

- **Assortment monitoring:** track which A101 products appear for selected searches, category URLs, or product groups.
- **Price tracking:** collect current, original, discounted, and display price fields for products in a chosen TRY price band.
- **Availability reporting:** monitor stock flags, enabled status, quantity limits, sales channels, and detail availability when those fields are present.
- **Catalog enrichment:** append product IDs, barcodes, brands, descriptions, category paths, image URLs, and merchandising attributes to internal item records.
- **Campaign and collection analysis:** review public collection labels, badges, variants, and category placement for merchandising workflows.
- **Recurring reporting:** schedule the same query, URL, category, or price-band inputs to compare product records over time.
- **Agentic research workflows:** let an internal agent collect a scoped product dataset, validate the record shape, summarize changes, and route records to the next workflow step.

### Real-World Questions This Data Can Answer

- Which A101 products match a keyword, category URL, product URL list, catalog mode, or TRY price range?
- Which products are currently visible for a recurring product family or campaign search?
- Which products changed price, availability, quantity limits, badges, or collection membership since the previous run?
- Which product records include usable identifiers such as `product.product_id`, `product.barcode`, or `product.url` for catalog matching?
- Which categories, brands, and collection labels appear most often for a selected discovery term or source URL?
- Which records are strong candidates for enrichment, review, monitoring, or downstream catalog updates?
- Which products should be deduplicated or upserted when repeated runs produce the same public product identity?

### Quick Start

1. Choose whether to start from A101 URLs in `startUrls`, keyword searches in `queries`, or both.
2. Select the A101 catalog scope with `search_mode`: `A101 Ekstra` or `A101 Kapında`.
3. Add optional TRY price boundaries with `min_price` and `max_price` when you need a narrower product set.
4. Set a small `limit` for the first validation run and choose whether `enrich_data` should collect richer product details.
5. Run the actor in Apify Console, inspect the first dataset records, then increase coverage or schedule recurring runs once the output shape is confirmed.

### Input Parameters

The actor accepts A101 URLs, product search queries, catalog mode, optional TRY price filters, enrichment preference, and a per-input record limit.

| Parameter | Type | Description | Default |
| --- | --- | --- | --- |
| `startUrls` | array of strings | A101 search result URLs, category URLs, or individual product URLs. Use this when the exact source scope is already known. Homepage URLs are ignored. | - |
| `queries` | array of strings | Product search phrases such as a brand, product family, category, or campaign keyword. Each query is collected separately so records can be traced back to the discovery term. | - |
| `search_mode` | string | A101 catalog scope for all discovery inputs in the run. Allowed values: `A101 Ekstra`, `A101 Kapında`. | `A101 Ekstra` |
| `min_price` | number | Minimum product price in TRY. Only products priced at or above this value are included when the source provides pricing. | - |
| `max_price` | number | Maximum product price in TRY. Only products priced at or below this value are included when the source provides pricing. | - |
| `enrich_data` | boolean | When enabled, the actor collects richer product details when A101 provides them. Leave disabled for lighter validation or monitoring runs. | `true` |
| `limit` | integer | Maximum number of records to save per URL or query. Use lower values for validation and higher values for scheduled exports or ETL batches. Minimum: `1`. | - (form prefill: `100`) |

### Choosing Inputs

Use `queries` when you want A101 to discover products from keywords such as a brand, product family, category, or campaign term. Use `startUrls` when you already have a defined A101 search page, category page, or product URL and want a repeatable collection scope. Use individual product URLs for enrichment backfills or catalog checks against known items. Use category or search URLs for recurring assortment monitoring where the same source scope should be revisited over time.

`search_mode` controls whether the run targets `A101 Ekstra` or `A101 Kapında`; choose one mode per run so downstream comparisons stay clean. `min_price` and `max_price` narrow the dataset to a TRY price band, while leaving them empty improves discovery across a broader price range. When comparing segments, keep separate runs for different categories, price bands, catalog modes, or query groups so exports remain easier to audit. Start with a small `limit` to validate the record shape, then increase it after confirming the dataset matches your workflow.

### Input Recipes

- **Validation run:** use one simple `queries` value, the default `search_mode`, `enrich_data` enabled, and a small `limit` to inspect the product, pricing, availability, media, and merchandising fields.
- **Targeted category collection:** provide one A101 category URL in `startUrls`, set a practical `limit`, and use the same input repeatedly for category-level assortment monitoring.
- **Known product enrichment:** provide individual A101 product URLs in `startUrls` and keep `enrich_data` enabled when you need more complete product context for internal catalog matching.
- **Price-band monitoring:** combine `queries` with `min_price` and `max_price` to collect products inside a defined TRY range for pricing reports or review queues.
- **Kapında catalog check:** set `search_mode` to `A101 Kapında`, provide focused `queries`, and keep the run separate from A101 Ekstra exports.
- **Segmented analysis:** run separate inputs by brand, product family, category URL, catalog mode, or price band so downstream dashboards can compare segments without extra cleanup.

### Example Inputs

#### Example: query validation run

```json
{
  "search_mode": "A101 Ekstra",
  "queries": ["laptop"],
  "min_price": 10000,
  "max_price": 60000,
  "enrich_data": true,
  "limit": 10
}
````

#### Example: direct category URL run

```json
{
  "search_mode": "A101 Ekstra",
  "startUrls": ["https://www.a101.com.tr/elektronik/elektrikli-supurge/"],
  "enrich_data": true,
  "limit": 25
}
```

#### Example: Kapında price-band run

```json
{
  "search_mode": "A101 Kapında",
  "queries": ["kahve"],
  "min_price": 50,
  "max_price": 500,
  "enrich_data": false,
  "limit": 20
}
```

### Output

#### Output destination

The actor writes results to an Apify dataset as JSON records. The dataset is designed for direct consumption by analytics tools, ETL pipelines, AI agents, and downstream APIs with minimal post-processing.

The provided output contract contains one product record shape. If future exports include multiple entity types or record shapes, each shape should be documented separately based on the records returned by the actor.

#### Record envelope and stable identifiers

Each dataset item is a structured product record with grouped objects for `source_context`, `product`, `pricing`, `availability`, `media`, and `merchandising`. The recommended idempotency key is the composite key `source_context.source_id` + `product.product_id`; use `source_context.source_url` or `product.url` as a practical fallback when a URL-based upsert is easier for your system. Use the recommended key to deduplicate repeated runs, merge records into existing product tables, and update matching items over time. Stable identifiers make records easier to compare, sync, deduplicate, and route across recurring collection, warehouse loading, review queues, and monitoring workflows.

`source_context` provides provenance for the record, including the source identifier, public source URL, discovery query, page number, result position, reported item count, selected catalog mode, seed type, and enrichment status when present.

#### Example: enriched product record

```json
{
  "source_context": {
    "source_id": "a101_product_scraper",
    "source_url": "https://www.a101.com.tr/elektronik/lenovo-loq-83gs00l7tr-512-gb-8-gb-ram-i5-12600hx-15-6-full-hd-gaming-notebook_p-26063395",
    "query": "laptop",
    "page_number": 1,
    "position": 1,
    "total_item_count": 8,
    "platform_name": "ecom",
    "seed_type": "query",
    "enrichment_enabled": true,
    "enrichment_status": "enriched"
  },
  "product": {
    "product_id": "26063395",
    "barcode": "198155399961",
    "title": "Lenovo LOQ 83GS00L7TR 512 GB 8 GB RAM i5-12600HX 15.6\" Full HD Gaming Notebook",
    "brand": "Lenovo",
    "category": "Laptop & Notebook",
    "category_path": [
      "Elektronik",
      "Bilgisayar & Tablet",
      "Laptop & Notebook"
    ],
    "url": "https://www.a101.com.tr/elektronik/lenovo-loq-83gs00l7tr-512-gb-8-gb-ram-i5-12600hx-15-6-full-hd-gaming-notebook_p-26063395",
    "country": "Çin",
    "description": "Lenovo Loq 83Gs00l7tr 512 Gb 8 Gb Ram I5-12600hx 15.6\" Full Hd Gaming Notebook ürününü A101 güvencesiyle en uygun fiyata satın almak için hemen tıklayın!"
  },
  "pricing": {
    "currency": "TRY",
    "current_price": 42999,
    "original_price": 42999,
    "discounted_price": 42999,
    "current_price_text": "₺42.999,00",
    "original_price_text": "₺42.999,00",
    "detail_price": 42999
  },
  "availability": {
    "in_stock": true,
    "is_enabled": true,
    "min_quantity": 1,
    "max_quantity": 5,
    "daily_max_quantity": 5,
    "channels": [
      "Online Satışa Özel"
    ],
    "detail_availability": "in stock"
  },
  "media": {
    "images": [
      {
        "id": "1.jpg",
        "url": "https://cdn2.a101.com.tr/dbmk89vnr/CALL/Image/getcl/livephotos/8/26063395default/1.jpg",
        "type": "product",
        "is_external": true
      }
    ],
    "primary_image_url": "https://cdn2.a101.com.tr/dbmk89vnr/CALL/Image/getcl/livephotos/8/26063395default/1.jpg"
  },
  "merchandising": {
    "collections": [
      {
        "id": "S10011001",
        "name": "Babalar Günü-Elektronik"
      },
      {
        "id": "S1001",
        "name": "Babalar Günü - A101 Ekstra"
      },
      {
        "id": "S10861015",
        "name": "Hadi Alışveriş Kredisi ile Taksitli Öde"
      },
      {
        "id": "S10291005",
        "name": "A101 Ekstra Özel Banka Kampanyası"
      },
      {
        "id": "S10291004",
        "name": "Bonus Kampanyası"
      },
      {
        "id": "S10911025",
        "name": "hadi veresiye"
      },
      {
        "id": "S10911026",
        "name": "Hadi Kredi Kartınla Her Ay 1000 TL"
      },
      {
        "id": "S10531296",
        "name": "Peşin Fiyatına 6 Taksitli Ürünler"
      },
      {
        "id": "S1032",
        "name": "Ekstraya Özel Ürünler"
      },
      {
        "id": "S10291001",
        "name": "A101’de 1.750 TL’ye varan fırsat!"
      },
      {
        "id": "S10911052",
        "name": "Hadi ile 18 Aya Varan Taksit"
      },
      {
        "id": "S10911056",
        "name": "Banka Kampanyaları - A101 Ekstra"
      },
      {
        "id": "S10911046",
        "name": "Peşin fiyatına 6 taksit ürünler"
      },
      {
        "id": "S10911014",
        "name": "A101-Garanti Bankası"
      },
      {
        "id": "S10911059",
        "name": "A101 Ekstra - Garanti  Bankası Kampanyası"
      },
      {
        "id": "S10291003",
        "name": "Garanti Bonus Kampanyası"
      },
      {
        "id": "S10081014",
        "name": "Elektronik Ürünler"
      },
      {
        "id": "S10911068",
        "name": "Hadi Black Kredi Kartı Özel Okul Ödemeleri"
      },
      {
        "id": "S10861020",
        "name": "Hadi Black Kredi Kartı ile Ramaza Kampanyası"
      },
      {
        "id": "S10911070",
        "name": "Hadi Ramazan Kampanyası"
      },
      {
        "id": "S10411272",
        "name": "Aldın Aldın - Bilgisayar & Tablet"
      }
    ],
    "variants": [
      {
        "id": "26063395"
      }
    ],
    "variant_count": 1,
    "badges": [
      {
        "bgColor": "#EA242A",
        "frameColor": "#EA242A",
        "id": "6taksit",
        "text": "Peşin Fiyatına 6 Taksit",
        "textColor": "#FFFFFF"
      }
    ]
  }
}
```

### Field Reference

#### `source_context`

- **source\_context.source\_id** *(string, required)*: source identifier for the A101 product record family.
- **source\_context.source\_url** *(string, required)*: public A101 URL associated with the saved product record.
- **source\_context.query** *(string, optional)*: search query that produced the record when the run started from a keyword.
- **source\_context.page\_number** *(integer, optional)*: result page number within the collected scope.
- **source\_context.position** *(integer, required)*: product position within the collected result scope.
- **source\_context.total\_item\_count** *(integer, optional)*: reported count of matching items when available.
- **source\_context.platform\_name** *(string, optional)*: catalog surface label returned with the record.
- **source\_context.seed\_type** *(string, optional)*: input source type, such as a query or URL-derived seed.
- **source\_context.enrichment\_enabled** *(boolean, required)*: whether richer product detail collection was requested.
- **source\_context.enrichment\_status** *(string, optional)*: detail collection status when enrichment information is available.

#### `product`

- **product.product\_id** *(string, required)*: stable A101 product identifier.
- **product.barcode** *(string, optional)*: product barcode when A101 provides it.
- **product.title** *(string, required)*: product title.
- **product.brand** *(string, optional)*: product brand label.
- **product.category** *(string, optional)*: most specific category label available in the record.
- **product.category\_path** *(array of strings, optional)*: category hierarchy from broader to more specific labels.
- **product.url** *(string, required)*: public A101 product URL.
- **product.country** *(string, optional)*: source-provided country label when available.
- **product.description** *(string, optional)*: product description or detail text when available.

#### `pricing`

- **pricing.currency** *(string, required)*: currency code for numeric price fields.
- **pricing.current\_price** *(number, required)*: normalized current price in the listed currency.
- **pricing.original\_price** *(number, optional)*: original or normal price when available.
- **pricing.discounted\_price** *(number, optional)*: discounted price when available.
- **pricing.current\_price\_text** *(string, optional)*: source display text for the current price.
- **pricing.original\_price\_text** *(string, optional)*: source display text for the original price.
- **pricing.discount\_rate** *(number or string, optional)*: source-provided discount rate when available.
- **pricing.detail\_price** *(number, optional)*: price captured from richer product detail context when available.

#### `availability`

- **availability.in\_stock** *(boolean, optional)*: normalized stock availability flag.
- **availability.is\_enabled** *(boolean, optional)*: whether the product appears enabled in the public product data.
- **availability.min\_quantity** *(integer, optional)*: minimum purchase quantity when available.
- **availability.max\_quantity** *(integer, optional)*: maximum purchase quantity when available.
- **availability.daily\_max\_quantity** *(integer, optional)*: daily purchase quantity limit when available.
- **availability.channels** *(array of strings, optional)*: public sales channel labels associated with the product.
- **availability.detail\_availability** *(string, optional)*: availability text from richer product detail context when available.

#### `media`

- **media.images** *(array of objects, optional)*: product image records in source order.
- **media.images.id** *(string, optional)*: source image identifier.
- **media.images.url** *(string, optional)*: public product image URL.
- **media.images.type** *(string, optional)*: image type label.
- **media.images.is\_external** *(boolean, optional)*: whether the image is marked as external.
- **media.primary\_image\_url** *(string, optional)*: primary product image URL.

#### `merchandising`

- **merchandising.collections** *(array of objects, optional)*: public collection or campaign groupings attached to the product.
- **merchandising.collections.id** *(string, optional)*: collection identifier when available.
- **merchandising.collections.name** *(string, optional)*: collection or campaign name.
- **merchandising.variants** *(array of objects, optional)*: product variant records when available.
- **merchandising.variants.id** *(string, optional)*: variant identifier.
- **merchandising.variant\_count** *(integer, optional)*: number of variants reported for the product.
- **merchandising.badges** *(array of objects, optional)*: merchandising badges attached to the product.
- **merchandising.badges.bgColor** *(string, optional)*: badge background color value when provided.
- **merchandising.badges.frameColor** *(string, optional)*: badge frame color value when provided.
- **merchandising.badges.id** *(string, optional)*: badge identifier.
- **merchandising.badges.text** *(string, optional)*: visible badge text.
- **merchandising.badges.textColor** *(string, optional)*: badge text color value when provided.

### Data Model Notes

- **Identity fields:** use `source_context.source_id` + `product.product_id` for product-level matching, deduplication, and upserts; use `product.url` or `source_context.source_url` as a URL-based fallback.
- **Source and provenance fields:** `source_context` explains how the record was discovered and where it can be reviewed publicly.
- **Business attributes:** `product`, `pricing`, `availability`, `media`, and `merchandising` contain the main user-facing product attributes for analysis and reporting.
- **Point-in-time values:** prices, availability flags, quantity limits, result positions, and collection membership should be treated as values observed at run time.
- **Nested objects:** related attributes are grouped to keep JSON exports easier to inspect, validate, and load into downstream systems.
- **Optional fields:** null-check or presence-check fields that depend on the product page, catalog mode, availability, enrichment setting, or source-side data quality.
- **Repeated runs:** compare records across runs using stable identifiers plus Apify run metadata, stored input configuration, and dataset export timestamps.

### Data Quality, Guarantees, And Handling

- **Structured records:** results are normalized into predictable JSON objects for downstream use.
- **Best-effort extraction:** fields may vary by catalog mode, product availability, public page contents, UI experiments, or source-side changes.
- **Optional fields:** null-check optional fields in downstream code, dashboards, and review tools.
- **Deduplication:** use `source_context.source_id` + `product.product_id` as the strongest stable key, with `product.url` or `source_context.source_url` as fallback identifiers.
- **Freshness:** results reflect publicly available A101 product information at run time.
- **Repeated runs:** use the recommended idempotency key when syncing records into warehouses, CRMs, search indexes, vector stores, or monitoring systems.
- **Schema awareness:** downstream systems should rely on documented fields and handle newly missing optional fields gracefully.

### Tips For Best Results

- Start with a small `limit` to validate the output shape before scaling up.
- Use one catalog mode, category, query group, or price segment per run when you need cleaner comparisons.
- Leave `min_price` and `max_price` empty when the goal is broad discovery.
- Add price filters gradually to understand how each boundary changes coverage.
- Use `startUrls` for known category or product scopes and `queries` for discovery.
- Keep `enrich_data` enabled for catalog backfills that need richer product context.
- Schedule recurring runs for monitoring workflows instead of relying only on manual one-off exports.
- Store the input configuration used for each recurring workflow alongside the exported dataset.

### How to Run on Apify

1. Open the actor in Apify Console.
2. Configure the available input fields for the desired A101 catalog scope.
3. Set `limit` to control the maximum number of records saved per query or URL.
4. Click **Start** and wait for the run to finish.
5. Open the dataset and inspect the first records.
6. Download results in JSON, CSV, Excel, or another supported format.

### Agentic And API-First Usage

A101 Product Scraper can be used as a structured data acquisition step inside larger automated workflows. It gives agents, applications, and data pipelines a predictable product record shape that can be validated, deduplicated, summarized, and routed without asking downstream systems to infer the meaning of raw page content.

Agent workflow pattern:

1. Generate or select a scoped input from the supported schema.
2. Run the actor manually, on a schedule, or through Apify platform automation.
3. Wait for completion and read the dataset records.
4. Validate records against the field reference.
5. Upsert records into the downstream system using `source_context.source_id` + `product.product_id`.
6. Trigger analysis, enrichment, alerts, or human review.

Practical notes for agentic use:

- Keep prompts and automations grounded in `startUrls`, `queries`, `search_mode`, `min_price`, `max_price`, `enrich_data`, and `limit`.
- Start with small validation runs before allowing broad automated collection.
- Feed the Field Reference and a small output sample to downstream AI steps.
- Treat optional fields as nullable instead of asking agents to infer missing values.
- Store run ID, input configuration, and dataset export metadata outside the record when building audit trails.

### Scheduling & Automation

#### Scheduling

**Automated Data Collection**

Schedule runs to keep A101 product datasets current for monitoring, reporting, catalog enrichment, or alerting workflows. Use the same saved input for consistent comparisons across time.

- Navigate to **Schedules** in Apify Console.
- Create a new schedule, such as daily, weekly, or a custom cron interval.
- Configure input parameters for the catalog mode, URLs, queries, price filters, enrichment preference, and limit.
- Enable notifications for run completion.
- Add webhooks for automated processing.

#### Integration Options

- **BI dashboards:** monitor prices, availability, category movement, badges, and assortment coverage over time.
- **Data warehouses:** store recurring product snapshots for historical reporting, price trend analysis, and campaign review.
- **Scheduled exports:** deliver repeatable JSON, CSV, or Excel files to analysts and operations teams.
- **Webhooks:** trigger ingestion, validation, alerts, or downstream processing after each completed run.
- **Alerts and monitoring:** notify teams when selected products change availability, price, quantity limits, or merchandising status.
- **Search and vector indexes:** make product titles, descriptions, categories, images, and merchandising context searchable for internal tools or AI retrieval workflows.
- **Google Sheets or Airtable:** review smaller validation runs, category samples, or manual QA queues in lightweight operational tables.

### Export Formats And Downstream Use

- **JSON:** for APIs, applications, AI agents, and data pipelines that need nested records with full fidelity.
- **CSV or Excel:** for spreadsheet workflows, stakeholder review, sampling, and lightweight analysis.
- **API access:** for automated ingestion into internal systems after each completed run.
- **BI and warehouses:** for reporting, dashboards, historical analysis, price monitoring, and assortment tracking.
- **Search or vector indexes:** for discovery, semantic search, retrieval workflows, or agent context using product titles, descriptions, categories, and merchandising fields.

### Downstream Pipeline Guide

- **Idempotency:** use `source_context.source_id` + `product.product_id` for upserts, with `product.url` or `source_context.source_url` as fallback identifiers.
- **Null handling:** treat optional product, pricing, availability, media, and merchandising fields as nullable.
- **Type handling:** preserve numbers, booleans, arrays, and nested objects when exporting to JSON-first systems.
- **Flattening:** if exporting to CSV or Excel, flatten nested objects deliberately and keep the original JSON export for full fidelity.
- **Partitioning:** store run date, input segment, catalog mode, query, category URL, price band, or workflow name alongside records for easier analysis.
- **Change detection:** compare repeated runs by stable key and selected business fields such as `pricing.current_price`, `availability.in_stock`, `availability.max_quantity`, `merchandising.badges`, and `merchandising.collections`.
- **Quality checks:** monitor record count, duplicate rate, required identifiers, price field fill rates, and important optional field coverage.
- **Human review:** route records with missing critical fields, unusual prices, changed availability, or changed merchandising status into a review queue when needed.
- **Retention:** decide how long to keep raw exports versus normalized warehouse tables based on monitoring, audit, and reporting requirements.

### Performance

Estimated run times:

- **Small runs (< 1,000 outputs):** ~3-5 minutes.
- **Medium runs (1,000-5,000 outputs):** ~5-15 minutes.
- **Large runs (5,000+ outputs):** ~15-30 minutes.

Execution time varies based on filters, result volume, target availability, and how much information is returned per record. Highly filtered runs can finish faster, while broad discovery or detail-rich records may take longer.

### Limitations

- Availability depends on what A101 publicly exposes at run time.
- Some optional fields may be missing on sparse products, category-only records, unavailable products, or records collected without richer detail.
- Very broad searches may take longer or require a higher `limit` to collect enough records for analysis.
- Target-side changes can affect field availability, labels, naming, or product visibility.
- A101 Ekstra and A101 Kapında may expose different product coverage or catalog context.
- The actor provides structured public product data, not business advice, legal advice, valuation advice, or guaranteed completeness.

### Troubleshooting

- **No results returned:** check query spelling, direct URLs, catalog mode, price filters, and whether A101 has matching public products.
- **Fewer results than expected:** broaden price filters, raise `limit`, try a broader query, or verify that the selected catalog contains enough matching records.
- **Some fields are empty:** optional fields depend on what each public product record provides and whether richer detail is available.
- **Duplicate-looking records:** compare `source_context.source_id` + `product.product_id` and decide whether records represent the same product, variants, different discovery scopes, or repeated observations.
- **Run takes longer than expected:** reduce scope, lower `limit` for validation, or split broad collection into smaller query, URL, catalog, or price-band segments.
- **Output changed:** compare the current output with the Field Reference and include a small sample when reporting the issue.
- **Downstream import failed:** check JSON validity, nullable fields, nested objects, arrays, and whether your destination expects flattened columns.

### FAQ

#### What data does this actor collect?

It collects structured public A101 product records, including product identity, title, brand, category path, public URL, pricing, availability, media, merchandising context, and source context when available.

#### Can I filter by location, category, date, price, status, keyword, or other criteria?

The supported input filters are keywords through `queries`, A101 URLs through `startUrls`, catalog scope through `search_mode`, TRY price range through `min_price` and `max_price`, enrichment preference through `enrich_data`, and per-input volume through `limit`. The schema does not include location, date, status, radius, or sort parameters.

#### Why did I receive fewer results than my limit?

`limit` is a maximum per URL or query, not a guarantee. The selected catalog scope, query, category, price range, product availability, and public result count can all produce fewer records.

#### How should I choose a limit for my first run?

Start with a small `limit`, review the first dataset records, confirm the fields are useful, then increase the limit for scheduled exports or larger monitoring workflows.

#### Can I schedule recurring runs?

Yes. Use Apify schedules to run the same query, URL, catalog mode, price filter, and limit configuration on a recurring cadence.

#### How do I avoid duplicates across runs?

Use `source_context.source_id` + `product.product_id` as the main upsert key. If your workflow is URL-based, also compare `product.url` or `source_context.source_url`.

#### What is the best field to use as a unique key?

The strongest documented key is the composite of `source_context.source_id` and `product.product_id`. This identifies the product within the A101 product record family.

#### Can I use the output with AI agents or automated workflows?

Yes. The actor returns predictable JSON records that agents can validate against the Field Reference, summarize, compare, route, or upsert into downstream systems.

#### Can I export the data to CSV, Excel, or JSON?

Yes. Apify datasets support common export formats including JSON, CSV, Excel, and API-based access for downstream ingestion.

#### Does this actor collect private data?

No. The actor is intended for publicly available A101 product catalog information.

#### What should I include when reporting an issue?

Include the redacted input, run ID, expected versus actual behavior, a small output sample if useful, and the downstream destination or export format if the issue is pipeline-related.

### Compliance & Ethics

#### Responsible Data Collection

This actor collects publicly available product catalog information from A101 for legitimate business purposes, including:

- **Retail and e-commerce** research and market analysis.
- **Assortment, pricing, and availability** monitoring.
- **Catalog enrichment, reporting, and operational review** workflows.

This section is informational and not legal advice. Users are responsible for ensuring that their use of collected data complies with applicable laws, regulations, contractual obligations, and platform rules.

#### Best Practices

- Use collected data in accordance with applicable laws, regulations, and the target site's terms.
- Respect individual privacy and personal information.
- Use data responsibly and avoid disruptive or excessive collection.
- Do not use this actor for spamming, harassment, discrimination, or other harmful purposes.
- Follow relevant data protection requirements where applicable, such as GDPR, CCPA, or sector-specific rules.
- Review your own retention, access control, and data-sharing policies before operationalizing the dataset.

### Support

For help, use the actor page or Issues. Include the input used with sensitive values redacted, the run ID, expected versus actual behavior, a small output sample when relevant, and the downstream destination or export format if the issue is related to an import, export, or pipeline workflow.

# Actor input Schema

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

Provide one A101 URL per line, such as https://www.a101.com.tr/arama?k=airpods, https://www.a101.com.tr/elektronik/elektrikli-supurge, or an individual product URL ending in \_p-26073264. Homepage URLs are ignored.

## `queries` (type: `array`):

Enter one query per line, such as a product family, brand, category, or campaign keyword. Each query is collected separately so downstream exports can trace records back to the discovery term.

## `search_mode` (type: `string`):

Choose A101 Ekstra for the standard online catalog or A101 Kapında for the Kapında catalog. The selected mode applies to all discovery inputs in the run.

## `min_price` (type: `number`):

Only include products priced at or above this TRY amount. Leave empty when there is no lower price boundary.

## `max_price` (type: `number`):

Only include products priced at or below this TRY amount. Leave empty when there is no upper price boundary.

## `enrich_data` (type: `boolean`):

Enable richer detail collection for more complete product records, including additional product context when A101 provides it. Leave disabled for faster validation runs or lightweight monitoring.

## `limit` (type: `integer`):

Choose the maximum number of records to save for each source URL or search query. Use a smaller value for validation and a larger value for scheduled exports or ETL batches.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.a101.com.tr/elektronik/elektrikli-supurge/"
  ],
  "search_mode": "A101 Ekstra",
  "enrich_data": true,
  "limit": 100
}
```

# Actor output Schema

## `results` (type: `string`):

Structured A101 product records saved by this run. Use this link for review, export, BI dashboards, scheduled ETL syncs, or agent workflows.

# 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 = {
    "startUrls": [
        "https://www.a101.com.tr/elektronik/elektrikli-supurge/"
    ],
    "limit": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("fatihtahta/a101-product-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 = {
    "startUrls": ["https://www.a101.com.tr/elektronik/elektrikli-supurge/"],
    "limit": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("fatihtahta/a101-product-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "startUrls": [
    "https://www.a101.com.tr/elektronik/elektrikli-supurge/"
  ],
  "limit": 100
}' |
apify call fatihtahta/a101-product-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=fatihtahta/a101-product-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "A101 Product Scraper | Fast & Reliable",
        "description": "Extract A101 product data at scale with pricing, availability, category paths, images, variants, badges, campaign collections, and A101 Ekstra/Kapında coverage. Built for enterprise-grade Turkish retail intelligence, assortment monitoring, and automated analytics pipelines.",
        "version": "0.1",
        "x-build-id": "CJvwPtRc5EEFw8Zbm"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/fatihtahta~a101-product-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-fatihtahta-a101-product-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/fatihtahta~a101-product-scraper/runs": {
            "post": {
                "operationId": "runs-sync-fatihtahta-a101-product-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/fatihtahta~a101-product-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-fatihtahta-a101-product-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "startUrls": {
                        "title": "Add A101 URLs",
                        "type": "array",
                        "description": "Provide one A101 URL per line, such as https://www.a101.com.tr/arama?k=airpods, https://www.a101.com.tr/elektronik/elektrikli-supurge, or an individual product URL ending in _p-26073264. Homepage URLs are ignored.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "queries": {
                        "title": "Add Product Search Queries",
                        "type": "array",
                        "description": "Enter one query per line, such as a product family, brand, category, or campaign keyword. Each query is collected separately so downstream exports can trace records back to the discovery term.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "search_mode": {
                        "title": "Select A101 Catalog",
                        "enum": [
                            "A101 Ekstra",
                            "A101 Kapında"
                        ],
                        "type": "string",
                        "description": "Choose A101 Ekstra for the standard online catalog or A101 Kapında for the Kapında catalog. The selected mode applies to all discovery inputs in the run.",
                        "default": "A101 Ekstra"
                    },
                    "min_price": {
                        "title": "Set Minimum Price",
                        "minimum": 0,
                        "type": "number",
                        "description": "Only include products priced at or above this TRY amount. Leave empty when there is no lower price boundary."
                    },
                    "max_price": {
                        "title": "Set Maximum Price",
                        "minimum": 0,
                        "type": "number",
                        "description": "Only include products priced at or below this TRY amount. Leave empty when there is no upper price boundary."
                    },
                    "enrich_data": {
                        "title": "Collect Richer Product Details",
                        "type": "boolean",
                        "description": "Enable richer detail collection for more complete product records, including additional product context when A101 provides it. Leave disabled for faster validation runs or lightweight monitoring.",
                        "default": true
                    },
                    "limit": {
                        "title": "Set Records per Input",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Choose the maximum number of records to save for each source URL or search query. Use a smaller value for validation and a larger value for scheduled exports or ETL batches."
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
