Tracking consumer electronics pricing across major regional retailers requires continuous ingestion of volatile catalog data. Citilink is one of Russia's largest electronics, computer, and home-appliance retailers. However, scraping its catalog directly via standard HTTP clients frequently leads to request blocks caused by anti-bot mitigation services like Qrator, alongside complex nested variant structures and pagination ceilings.
When tracking pricing shifts, stock changes, or gathering consumer sentiment across thousands of stock-keeping units (SKUs), data teams need deterministic output schemas rather than unstructured HTML blobs. The Citilink Scraper actor provides structured extraction across four operational modes, resolving nested product variants, full specifications, and individual customer reviews into predictable JSON payloads.
Operational Modes and Selection Strategies
The scraper organizes requests through four distinct operations defined in the mode parameter:
-
search: Free-text search matching keywords such asноутбукoriphone. -
byCategory: Scrapes structured catalog listings via a slug (e.g.,smartfony) or a category path. -
productDetails: Deep spec extraction for specific listings using product IDs or canonical URLs. -
reviews: Full-text review scraping distinct from the aggregated star ratings.
For category tracking, using byCategory avoids the relevance-based ranking drift inherent in keyword searches. The scraper traverses catalog trees and yields items with pricing fields including priceCurrent, priceOld, discountPercent, and bonusPoints (all in RUB).
When querying broad categories, sorting behavior must be handled carefully. Citilink orders results by internal relevance by default. When setting sortBy to non-default values like priceAsc, priceDesc, discount, rating, opinions, or reviews, the actor fetches a wider window of results in relevance order, applies the sort across that collected batch, and truncates output to maxItems. For accurate top-N extraction on deep categories, combining sortBy with narrow bounds using minPrice and maxPrice prevents out-of-scope truncation.
{
"mode": "byCategory",
"category": "smartfony",
"inStockOnly": true,
"minPrice": 30000,
"maxPrice": 80000,
"sortBy": "discount",
"maxItems": 100
}
Extracting Product Specifications and Multi-Axis Variants
A persistent structural challenge in e-commerce ingestion is resolving product siblings. Many listings share a single model family but diverge across storage, RAM, or finish.
In productDetails mode, passing an array to productIds extracts not only static technical parameters but dynamic variant groupings:
-
properties: Full specifications structured as name/value pairs, including technical measurement units (measure). -
colorVariants: Sibling models differing by color, containing their specificid,productUrl,color,isAvailable, andimageUrl. -
variantGroups: Multi-dimensional variant axes (such as storage capacity combined with color options), linking all available sibling product IDs. -
earliestDeliveryDateandpickupStoresAvailable: Granular logistics counters reflecting immediate inventory availability.
{
"mode": "productDetails",
"productIds": [
"2143346",
"https://www.citilink.ru/product/televizor-samsung-qe65q80dauxru-65-4k-ultra-hd-3840x2160-2135640/"
],
"maxItems": 10
}
This configuration extracts raw specs alongside secondary listing data such as vendorCode, ratingBreakdown (opinion histograms), and topReview records. Empty fields are omitted entirely by the actor rather than populated with null markers.
Mining Customer Sentiment via Dedicated Review Scrapes
Aggregate star ratings (rating, opinionsCount) provide high-level signals, but qualitative defect tracking and product monitoring require textual commentary.
Running the actor with mode: "reviews" retrieves individual long-form reviews rather than product metadata. Output items contain:
-
titleandcontent: The raw text written by the user. -
viewsCount: Engagement depth. -
likesanddislikes: User helpfulness voting counts. -
authorNicknameandauthorSuid: User identifiers. -
createdAtandmodifiedAt: ISO timestamps.
The maxReviewsPerProduct integer sets an upper bound (from 1 to 200) per requested item ID.
{
"mode": "reviews",
"productIds": ["2143346"],
"maxReviewsPerProduct": 50
}
Execution Walkthrough
Integrating the scraper into an ETL pipeline involves configuring parameters, running the task, and pulling the dataset.
-
Define the payload: Choose the operational
mode(search,byCategory,productDetails, orreviews) and establish item bounds usingmaxItemsormaxReviewsPerProduct. -
Set targeting filters: Restrict noise by defining
inStockOnly: true, applyingminRating, or usingminPrice/maxPricethresholds. -
Execute via API or client: Trigger the run passing the input JSON. Citilink's Qrator protection requires proxy routing, handled automatically via the required
proxyConfigurationparameter (the default datacenter group is sufficient). - Ingest dataset items: Fetch emitted items from the default dataset storage.
A minimal Python pipeline using the Apify API client demonstrates the execution:
from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run_input = {
"mode": "search",
"searchQuery": "ноутбук",
"minPrice": 50000,
"maxPrice": 120000,
"inStockOnly": True,
"sortBy": "priceAsc",
"maxItems": 50,
"proxyConfiguration": {"useApifyProxy": True}
}
run = client.actor("crawlerbros/citilink-scraper").call(run_input=run_input)
dataset_items = client.dataset(run["defaultDatasetId"]).list_items().items
for item in dataset_items:
print(f"{item.get('name')} -> {item.get('priceCurrent')} RUB (In Stock: {item.get('isAvailable')})")
Cost and Event-Based Accounting
Billing for this actor runs strictly on a pay-per-event pricing model without compute-time fees or usage-tier subscriptions.
Runs incur two exact charge types:
-
Actor Start (
apify-actor-start): $0.005 per GB of memory allocated to the run, charged once upon initialization. -
Result (
apify-default-dataset-item): $0.005 per emitted item under the FREE volume tier.
For higher monthly consumption, the per-result event scales across volume tiers:
- BRONZE: $0.00433 per result
- SILVER: $0.00367 per result
- GOLD / PLATINUM / DIAMOND: $0.003 per result
Extracting 1,000 product records on a standard 1 GB allocation under the default tier costs $0.005 for the actor start plus $5.000 for the 1,000 result events, totaling $5.005.
Boundary Conditions and Tool Limitations
This actor does not place orders, manage user carts, or access authenticated account dashboards; it functions strictly as a data extraction engine for publicly listed catalog endpoints. Furthermore, sorting on broad categories relies on sorting an internally fetched candidate window rather than server-side whole-catalog re-indexing. When precise global rankings on massive catalogs are required, splitting scrapes across granular price brackets produces more complete coverage than relying on a single broad sort parameter.
Runs in this article used Citilink Scraper - Russian Electronics Store Products. Its README is the reference for input fields and output structure; this post is only one path through them.
Top comments (0)