Building price-monitoring pipelines for retail apparel often runs into heavy anti-bot infrastructure. Targets like Kohl’s enforce Akamai Bot Manager policies that issue HTTP 403 Access Denied responses to automated requests, even when using specialized TLS-impersonation libraries like curl_cffi or httpx. Bypassing these edge controls typically forces developers into maintaining residential proxy pools, which adds operational complexity and direct network costs.
Gap Inc’s online footprint—covering Old Navy, Gap, Gap Factory, Banana Republic, and Athleta—presents a structural alternative. All five storefronts feed their front-end web apps using a shared public search API (api.gap.com/commerce/search/v2/product_listings). This endpoint does not require session cookies, authentication headers, or browser rendering engines. It responds cleanly to standard datacenter HTTP requests, providing direct access to product listings, price points, size availability, and variant SKUs across both US and Canadian markets.
The Gap Inc Scraper exposes this endpoint as a structured service, allowing you to ingest cross-brand catalog state without managing proxy rotation or browser headless sessions.
Structured API Access Across Five Brands
Instead of parsing HTML DOM trees that change with front-end deployments, querying the search backend returns clean, predictable JSON objects. The upstream API structures data around individual color swatches. Rather than returning a single generic product record with nested arrays of options, each distinct color variation functions as its own record. This mirrors the consumer checkout experience, where different colors within the same style frequently carry unique price points, clearance status, and stock levels.
Every record emitted to the default dataset contains target fields mapped directly from the JSON payload:
-
Identifiers:
productId(style-level ID) andskuId(color-specific SKU). -
Product Details:
name,brand,colorName(broad family likeBlue), andcolorShade(specific shade likeNavy). -
Pricing Dynamics:
effectivePrice,regularPrice,priceCurrency(USDorCAD),percentageOff,onSale, anddiscountType(Promo,Markdown, orRegular). -
Promotional Context:
badges(e.g.,Best Seller) andpromoMessage(e.g.,Extra 50% off at checkout). -
Inventory & Metadata:
availableSizes,totalSwatchCount,vendorId,reviewScore, andreviewCount. -
Media & Links:
imageUrl,imageUrls(full detail gallery),videoUrl, and canonicalproductUrl.
When fields do not exist for a specific item—such as a new item lacking reviews or a style without an embedded video—the system omits the key entirely rather than injecting null or placeholder strings like "N/A".
Configuring Search Inputs and Server-Side Facets
To pull specific product sets, you configure execution parameters using the Actor's input schema. Because the underlying search endpoint requires a non-empty string, broader category scans rely on combining high-frequency keywords with targeted filtering facets.
Key schema properties include:
-
brand(string, required): Controls the target storefront. Acceptson(Old Navy),gap(Gap),gapfs(Gap Factory),br(Banana Republic), orat(Athleta). -
market(string): Acceptsusorca. Selectingcatargets Canadian storefronts with distinct catalogs, CAD pricing, andgapcanada.caproduct URLs (Gap Factory lacks a Canadian site and automatically falls back tous). -
searchQuery(string, required): The search string fed to the API. Broad terms likejeans,tee, ornewallow you to capture wide slices of a category. -
department(string): Restricts queries to server-side categories such asWomen,Men,Girls,Boys,Toddler,Baby,Gender Neutral, orMaternity. -
additionalFacets(array): Accepts customname=valuestrings (e.g.,["fit=Skinny", "wash=Light Wash"]) to tap into specific category filters exposed on the native storefront sidebar.
Because sorting parameters like sortBy: "price" are executed over an evaluated candidate pool client-side (up to 5x maxItems, capped at 500 items) to account for upstream API limitations, filtering on the server side using parameters like minPrice, maxPrice, onSaleOnly, and priceType keeps your run efficient and precise.
Here is an example input configuration designed to track clearance inventory for women's activewear at Athleta:
{
"brand": "at",
"searchQuery": "leggings",
"department": "Women",
"priceType": "MARKDOWN",
"minReviewScore": "4",
"maxItems": 100
}
If you need to query Canadian inventory for cross-border price parity analysis on core denim at Gap, you can use a configuration like this:
{
"brand": "gap",
"market": "ca",
"searchQuery": "jeans",
"sortBy": "price",
"sortDir": "asc",
"maxItems": 50
}
Step-by-Step Execution Walkthrough
Executing a scrape run through Apify's infrastructure or API follows a straightforward path:
-
Define your task JSON: Create your input payload specifying the targeted
brand,searchQuery, and schema bounds such asmaxItems. - Trigger the run: Execute the Actor via the Apify Console or call the API endpoint programmatically using Python or JavaScript SDKs.
-
Stream or fetch dataset output: As the Actor queries
api.gap.com, records are pushed directly to the default dataset.
Below is an example of running the scrape task programmatically using the apify-client Python SDK:
from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run_input = {
"brand": "on",
"market": "us",
"searchQuery": "jeans",
"department": "Women",
"onSaleOnly": True,
"additionalFacets": ["fit=Skinny"],
"maxItems": 100,
}
# Run the Actor and wait for completion
run = client.actor("crawlerbros/gap-inc-scraper").call(run_input=run_input)
# Fetch results from the run's default dataset
dataset_items = client.dataset(run["defaultDatasetId"]).list_items().items
for item in dataset_items:
print(
f"SKU: {item.get('skuId')} | {item.get('name')} - "
f"{item.get('colorShade', item.get('colorName'))}: "
f"${item.get('effectivePrice')} {item.get('priceCurrency')}"
)
Understanding Event Pricing Mechanics
This Actor operates entirely under a Pay-Per-Event pricing structure. Charges are based strictly on execution events rather than compute time or variable infrastructure usage:
-
Actor Start (
apify-actor-start): $0.005 per GB of memory allocated to the run (charged once upon container launch, with a minimum 1 GB allocation). -
Dataset Results (
apify-default-dataset-item): $0.005 per emitted item record at the base tier (discounting down through volume tiers to $0.00433 at BRONZE, $0.00367 at SILVER, and $0.003 at GOLD, PLATINUM, and DIAMOND tiers).
Under this fixed event schema, a standard run generating 100 dataset items on a 1 GB container costs exactly $0.005 for the actor start event plus $0.50 for the 100 result items, yielding a predictable total execution cost of $0.505.
Operational Limitations
Passing invalid or misspelled string parameters inside the additionalFacets array will cause the upstream Gap Inc API to reject the query payload outright, returning an empty dataset with zero records rather than ignoring the unknown facet or raising an explicit error message.
Gap Inc Scraper (Gap, Old Navy, Banana Republic, Athleta) is what these steps drive. The README covers the inputs this article skipped, including the ones that change how much a run costs.
Top comments (0)