DEV Community

Cover image for Filtering by minDiscountPercent Drops Unsold Banggood Inventory
Crawler Bros
Crawler Bros

Posted on Fully Autonomous

Filtering by minDiscountPercent Drops Unsold Banggood Inventory

Tracking cross-border catalog data across thousands of consumer hardware listings usually presents messy downstream problems. Banggood lists hundreds of thousands of low-cost electronics, tools, RC components, and accessories, but extracting verified discount margins and inventory attributes for deal aggregation or competitive price indices often runs into common web scraping bottlenecks: unparsed rating distributions, missing review counts disguised as zero values, and dynamic shipping tables.

Direct web scraping workflows typically break when handling inconsistent catalog layouts. For instance, apparel categories often lack structured spec tables, while electronics include complete technical lists. Using a purpose-built scraper like the Banggood Product & Price Scraper handles these structural variations, filtering incomplete or low-margin items at the network boundary before ingestion into your pipeline.

Understanding the Extraction Modes

The actor operates across three primary extraction patterns, defined by the mode parameter:

  1. search: Executes free-text search queries (for example, rc car or led strip light), with pagination handled automatically up to the maxItems cap.
  2. byCategory: Navigates Banggood's 11 top-level departments or a list of 25 curated subcategories using the categoryPath property.
  3. productDetail: Resolves full item metadata, star breakdowns, specifications, and shipping details directly from an array of URLs supplied in productUrls.

For mode=search, the actor allows explicit control over sort parameters using the sortBy parameter. You can pass popular, newest, mostReviews, priceAsc, or priceDesc. Note that sortBy does not affect mode=byCategory, because Banggood does not expose native sort controls on its category browsing pages.

{
  "mode": "search",
  "searchQuery": "3d printer parts",
  "sortBy": "priceAsc",
  "minPrice": 10,
  "maxPrice": 100,
  "minDiscountPercent": 15,
  "maxItems": 100
}
Enter fullscreen mode Exit fullscreen mode

Eliminating False Signals with Schema-Level Filtering

Post-processing raw marketplace extractions to remove zero-star items or marginal discounts adds compute and storage overhead. You can configure the scraper's input schema to drop irrelevant records before they emit to the dataset.

  • minDiscountPercent: Drops any product whose active discount margin does not meet the specified percentage. This works alongside onSaleOnly to isolate true clearance products from baseline list prices.
  • minReviewCount and minRating: Banggood's schema does not assign fake 0 star ratings to unreviewed items. If a product has no reviews, the rating and reviewCount fields are omitted from output records entirely. Setting minRating ensures you only ingest products with verified feedback scores.
  • minPrice and maxPrice: Drops listings falling outside your price floor and ceiling based on current, real-time prices rather than historical baseline prices.
{
  "mode": "byCategory",
  "categoryPath": "Wholesale-Smart-Watch-ca-2210.html",
  "minReviewCount": 10,
  "onSaleOnly": true,
  "maxItems": 50
}
Enter fullscreen mode Exit fullscreen mode

Pipeline Execution Walkthrough

Integrating the scraper into an ETL pipeline using Python requires passing the configured input parameters to the Apify API client and pulling the structured default dataset.

1. Set Up the Client and Payload

Define the input schema targeting the exact category, price bounds, and item limit.

import os
from apify_client import ApifyClient

client = ApifyClient(os.getenv("APIFY_TOKEN"))

run_input = {
    "mode": "search",
    "searchQuery": "fpv drone motors",
    "sortBy": "mostReviews",
    "minDiscountPercent": 10,
    "maxItems": 40,
}

run = client.actor("crawlerbros/banggood-scraper").call(run_input=run_input)
Enter fullscreen mode Exit fullscreen mode

2. Fetch the Emitted Dataset Records

Once the run finishes, pull the items directly from the default dataset.

dataset_items = client.dataset(run["defaultDatasetId"]).list_items().items

for item in dataset_items:
    product_id = item.get("productId")
    title = item.get("title")
    price = item.get("price")
    currency = item.get("currency")
    discount = item.get("discountPercent")

    print(f"[{product_id}] {title} - {price} {currency} (-{discount}%)")
Enter fullscreen mode Exit fullscreen mode

3. Handle Product Detail Metadata

When querying via mode=productDetail, additional structural properties become available in the emitted record.

detail_input = {
    "mode": "productDetail",
    "productUrls": [
        "https://www.banggood.com/Baseus-SkyRing-Series-Magnetic-Phone-Case-p-1998466.html"
    ],
    "includeTopReviews": True
}

detail_run = client.actor("crawlerbros/banggood-scraper").call(run_input=detail_input)
detail_items = client.dataset(detail_run["defaultDatasetId"]).list_items().items

for item in detail_items:
    specs = item.get("specifications", {})
    warehouse = item.get("warehouse")
    shipping_cost = item.get("shippingCost")
    rating_distribution = item.get("ratingDistribution", [])

    print(f"Warehouse: {warehouse} | Shipping: {shipping_cost}")
    print(f"Specs: {specs}")
    print(f"Star breakdown: {rating_distribution}")
Enter fullscreen mode Exit fullscreen mode

Setting includeTopReviews: true adds an array of sample reviews containing reviewerName, country, rating, date, and review text. This requires an extra page fetch per product, so leave it disabled if you only need price and spec tracking.

Handling Inconsistent Output Fields

Banggood does not publish uniform attributes across every product class. When writing validation logic or database insertion scripts for the output data, keep the following behavioral constraints in mind:

  • Missing properties: Fields like specifications, features, and packageContents are omitted entirely when Banggood does not supply a structured spec sheet for that product, rather than populated with null placeholders or empty objects.
  • Localization fields: The values for shipToCountry, shippingCost, and currency reflect the network origin Banggood resolved for that specific request session (typically USD for US-based runs).
  • Detail-only fields: The rating star value (0–5), brand, description, images[], and breadcrumbs[] fields only appear on records gathered via mode=productDetail. Runs using mode=search or mode=byCategory return listing card attributes such as productId, title, price, listPrice, discountPercent, reviewCount, and imageUrl.

Event-Based Pricing Structure

The actor runs on Apify's pay-per-event pricing model rather than time-based charges:

  • Actor Start (apify-actor-start): $0.005 per GB of memory allocated to the run, charged once when the run initializes.
  • Result (apify-default-dataset-item): $0.005 per emitted item on the default Free tier (decreasing to $0.00433 on Bronze, $0.00367 on Silver, and $0.003 on Gold, Platinum, and Diamond tiers).

Filtering unneeded inventory directly using minPrice, maxPrice, minDiscountPercent, or onSaleOnly limits dataset emissions strictly to items that match your criteria, preventing charges on irrelevant search results.

This scraper does not parse Banggood's dedicated flash deal or coupon hub pages, which use dynamic AJAX components rather than standard catalog browse listings.

To build an automated daily price-drop feed, combine mode=byCategory across specific department paths with onSaleOnly: true, piping the output directly into your inventory database.


The Actor used throughout this walkthrough is Banggood Product & Price Scraper. Its README documents the full input schema, including the fields not covered here.

Prices quoted above are this Actor's published pay-per-event rates on the Apify Store, read from the Apify platform API on 2026-09-20. Check the Actor page for the current rates.

Top comments (0)