Kohl's Scraper - Products, Prices, Ratings & Reviews avatar

Kohl's Scraper - Products, Prices, Ratings & Reviews

Pricing

from $1.60 / 1,000 product records

Go to Apify Store
Kohl's Scraper - Products, Prices, Ratings & Reviews

Kohl's Scraper - Products, Prices, Ratings & Reviews

Scrape Kohl's (kohls.com) products by keyword search or category browsing. Extract product names, brands, prices, descriptions, ratings, customer reviews and detailed product information. Ideal for price comparison, competitor analysis, product research and retail market intelligence.

Pricing

from $1.60 / 1,000 product records

Rating

0.0

(0)

Developer

Abot API

Abot API

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

1

Monthly active users

7 days ago

Last modified

Categories

Security

Limited permissions

Share

Kohl's Product Scraper

Scrape Kohls.com product listings: keyword search, category browsing, full product details, prices, ratings and customer reviews. Kohl's is one of the largest US department-store chains (clothing, shoes, home, kitchen, bedding, toys, jewelry and more), and this actor turns its catalog into clean structured rows for price monitoring, assortment analytics and competitor research.

Why This Scraper?

  • Two ways in. Point it at keyword searches, or paste any storefront links - search pages, category/catalog pages and product pages all walk with the same grammar.
  • Deep product records. Every listing row carries title, price (with sale and was-price ranges), rating, review count, badges and the full colorway list; detail enrichment adds the description, brand, per-variant SKUs, availability, sizes, image gallery and breadcrumbs.
  • Customer reviews included. Rating summary, star distribution and up to 20 review texts per product, with verified-purchaser and fit/size feedback fields.
  • Scheduled-run friendly. Incremental mode classifies every product NEW / UPDATED / UNCHANGED / EXPIRED across runs, so a daily monitor pushes only what moved, and resume mode continues an interrupted walk exactly where it stopped.
  • Fast and light. The actor reads the storefront's own page data directly over US connections, a few seconds per page, and moves to a fresh connection automatically when one is refused.

Use Cases

  • Who: pricing teams tracking Kohl's promos on competitive assortments - sale and was-price ranges land per row, updated per scheduled run.
  • Who: sellers and brands auditing their shelf - badges (Best Seller, clearance), colorway coverage, availability and review velocity per product.
  • Who: analysts building category datasets - walk any catalog page with the same card grammar and export straight to CSV/Excel or a warehouse.

Data You Get

Sample shape: values are illustrative placeholders, not from a live record.

FieldExample
titleNike V5 RNR Women's Running Shoes
brandNike
price / priceMax25.99 / 39.99 (sale range)
wasPrice / wasPriceMax39.99 / null (regular price)
priceLabelFor Price, Add To Cart (MAP-hidden items)
rating4.2
reviewsCount468
badges["Best Seller"]
colors["White", "Pink Black", "Silt Red"]
colorsOutOfStock["White Grey Metallic"]
sizes["5", "5.5", "6", ...]
sku / skus48518782 / [per-variant SKUs]
availabilityInStock
descriptionFull product description text
imageUrlsFull image gallery
breadcrumbs[Women > Shoes > Running Shoes]
department / category / subcategoryWomens / Shoes / Sneakers (first three levels of the product-page breadcrumb trail, with the store root and the product's own leaf dropped; product-page rows only, null otherwise)
reviewsAverage / reviewsRecommended4.2 / 350
ratingDistribution[{stars: 5, count: 300}, ...]
reviews[{rating, title, text, author, verifiedPurchaser, fit, ...}]
changeType / changedFieldsNEW / UPDATED / [price] (incremental mode)
priceChanges / variantChangesold and new value per moved price field / per-variant changes (present only on compact UPDATED rows, compactUpdates on)

Each run also writes a RUN_SUMMARY record to the run's key-value store: records pushed, product-page enrichments charged, review units charged, pages served and whether the run was partial.

How to Use

Run it from your code

Python:

from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("abotapi/kohls-com-scraper").call(run_input={
"mode": "search",
"searchTerms": ["womens jeans"],
"maxItems": 50,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item["title"], item["price"])

JavaScript:

import { Actor } from 'apify';
const run = await Actor.call('abotapi/kohls-com-scraper', {
mode: 'urls',
urls: ['https://www.kohls.com/catalog/mens-clothing.jsp'],
maxItems: 50,
});
const { default: dataset } = await Actor.openDataset(run.defaultDatasetId);
await dataset.forEach((item) => console.log(item.title, item.price));

Search by keyword:

{
"mode": "search",
"searchTerms": ["womens jeans", "air fryer"],
"maxItems": 50
}

Walk a category:

{
"mode": "urls",
"urls": ["https://www.kohls.com/catalog/mens-clothing.jsp"],
"maxItems": 100
}

One product, reviews capped:

{
"mode": "urls",
"urls": ["https://www.kohls.com/product/prd-7327369/nike-v5-rnr-womens-running-shoes.jsp"],
"maxReviews": 5
}

Scheduled price monitor:

{
"mode": "search",
"searchTerms": ["womens jeans"],
"maxItems": 200,
"fetchReviews": false,
"incrementalMode": true
}

Leave urls empty-handed (omit it) and the actor walks its built-in three links: a keyword search page, a category page and a product page. An empty list also walks the built-in three links. On pasted search and category links, filter and sort parameters are kept on every page and a WS offset sets the start position; product links read that one product. A category link without its filter part (for example /catalog/mens-clothing.jsp) is matched to that category in the storefront's menu; a bare category link the menu does not know is skipped with a warning, so paste such links with their full address (including the CN= part). Links that are not search, category or product pages are skipped with a warning. A product link that no longer exists on the storefront is skipped with a warning and bills nothing. A search that matches nothing ends with the message "No results matched this run's inputs".

Tips

  • Start from a keyword search for quick pulls; paste category links for complete assortment walks.
  • The storefront semantic-matches nonsense queries to real results - a "no match" search is not reachable by input, so judge runs by row count and the run status message.
  • What incremental mode compares: rows from search and category pages compare only the listing-card fields (title, price, price range, was price, discount, price label, rating, review count, image, badges and colours); pasted product links compare the full product-page record (availability, colours out of stock, sizes, specs, sellers, description and categories as well). Reviews, scrape time, grid position, the card slot id (webId, which moves with the ranking) and list name are never compared. Use changeScope = priceAndStock to narrow the comparison to price fields; availability and colours out of stock are tracked only on product-link rows. EXPIRED means a product dropped out of the scanned listing; without opening its page a listing drop and a delisting look the same, so read availability for stock. Changing the scope or the ignore list changes the automatic baseline, so the first run afterwards reports every row as NEW; set a State key to keep one baseline.
  • Compact UPDATED rows no longer carry the product-page data, so the product-page enrichment event and review units are not charged for them.
  • Scheduled incremental runs keep the walk cheap: unchanged rows are suppressed before any product page is re-read and bill nothing.
  • Sale prices arrive as ranges (price + priceMax); MAP-hidden items carry priceLabel "For Price, Add To Cart" and no price until a detail read finds one.

Input Parameters

ParameterTypeDefaultDescription
modeselecturlssearch walks keyword searches; urls walks pasted storefront links.
searchTermsstring listwomens jeansKeyword searches to walk (search mode). If a run sends search terms but leaves the sample links untouched, the search terms are walked and the sample links are ignored.
urlsURL list3 example linksSearch pages, category/catalog pages and product pages (links mode).
maxItemsinteger20Maximum records per run, up to 100000. 0 means the 100000 cap.
fetchDetailscheckboxtrueRead each product's detail page (description, SKUs, sizes, gallery).
fetchReviewscheckboxtrueCollect rating summary and review texts per product.
maxReviewsinteger20Review texts collected per product, up to 1000. 0 skips texts.
incrementalModecheckboxfalseClassify rows NEW/UPDATED/UNCHANGED/EXPIRED across scheduled runs.
emitUnchangedcheckboxfalseAlso emit rows whose tracked fields did not change.
emitExpiredcheckboxfalseEmit EXPIRED rows for products that left a fully-scanned scope.
proxyConfigurationproxyAutomatic USAutomatic US proxies work for most runs. Residential US gives the most reliable results; it is your choice and uses more of your plan's proxy traffic.
resumeFromRunIdstring(hidden)Internal: continues an interrupted run; collected records are skipped.
stateKeystring(hidden)Internal: names the incremental baseline; empty derives it from the scope.
expireAfterMissedScansinteger1With Emit expired records: mark a product EXPIRED only after it was missing from this many consecutive complete scans.
changeScopeselectallall compares every field the row carries; priceAndStock marks a row UPDATED only when price, was price, discount or price label moved (availability and colours out of stock count on product-link rows only).
compactUpdatescheckboxfalseUPDATED and EXPIRED rows carry only identifiers, current price and availability, priceChanges and variantChanges. NEW rows stay full.
ignoreFieldsForChangesstring list(hidden)Ignore fields when detecting changes (incremental mode only): field names, or dotted paths such as offers.price, that never decide UPDATED. They stay in the output.
mcpConnectorsstring list(hidden)Internal: connector ids that receive records as they push.
notionParentPageUrlstring(hidden)Internal: parent page for the Notion connector.
maxNotifyListingsinteger50 (hidden)Internal: cap on records sent to connectors per run.

All fields are also accepted through the API exactly as documented, including the hidden internal ones.

Output Example

Sample shape: values are illustrative placeholders, not from a live record.

{
"recordId": "kohls:7327369",
"productId": "7327369",
"title": "Nike V5 RNR Women's Running Shoes",
"brand": "Nike",
"price": 95.0,
"priceMax": null,
"wasPrice": null,
"currency": "USD",
"rating": 4.2,
"reviewsCount": 468,
"badges": ["Best Seller"],
"colors": ["Pink Black", "White", "Silt Red"],
"availability": "InStock",
"url": "https://www.kohls.com/product/prd-7327369/nike-v5-rnr-womens-running-shoes.jsp"
}

Product rows with the detail enrichment on, from a live category walk.

Plan Requirement

This actor requires an Apify paid plan, because every page is read through Apify proxy connections and the Apify Free plan includes no proxy access. Automatic US proxies are the default and work for most runs; residential US proxies give the most reliable results (your choice, and they use more of your plan's proxy traffic). If the selected connection is refused for your account, the run says so in the log and continues on a backup connection where one is available; when none is, the run ends with a message asking you to upgrade at https://apify.com/pricing or supply your own proxy URLs.

FAQ

The actor collects publicly available product data from the storefront's own pages, at a polite pace, without logging into any account. Review your use case and the site's terms before running at scale.

Why does a run fail with a connection problem?

Individual proxy connections are occasionally refused. The actor retries each page on fresh connections (up to five per page) and stops early when the storefront refuses a long run of connections in a row, so a closed window ends quickly instead of running to the time limit. Retry later; the same input usually succeeds on the next run.

How much does a run cost?

You pay the actor's per-event pricing (see the Pricing tab) plus your Apify plan's proxy usage. Four things are billed. Apart from the run start, each is charged only for rows actually pushed to the dataset:

  • Actor start: one per run.
  • Dataset item: one per pushed row, every row.
  • Product-page enrichment: one per pushed row whose product page was read: listing rows with details on, and every pasted product link (a product link always reads its page, even with details off).
  • Review unit: one per pushed row that delivered review texts, regardless of how many (up to maxReviews, at most 1000).

Card-only listing rows (details off), suppressed rows, and unchanged listing rows in incremental mode bill no enrichment or review fee. A pasted product link is re-read on every run, so with Emit unchanged records on, its unchanged row is still billed the product-page enrichment and any review unit. Proxy traffic is billed separately by your Apify plan.

Can I track price changes daily?

Yes - schedule the run with incrementalMode on and the same inputs. Only NEW and UPDATED rows push, each with changedFields naming what moved.

Send results into your apps (MCP connectors)

Connect the actor to Notion, Google Sheets and other MCP-capable apps from the Apify Console: records this run pushed are delivered as they land, capped per run. Connector settings ship hidden in the input and need no attention unless you use connectors.

🔗 Want more fashion data?

Pair this actor with these related scrapers from the same team:

👗 Nuuly Scraper
Scrape Nuuly clothing rental products by category, brand or URL. Extract product names...
👗 Fashion Nova Scraper
Scrape Fashion Nova products by keyword, collection or URL. Extract product names...
👗 Showpo Scraper
Scrape Showpo women's fashion by keyword, collection or URL. Extract product prices...
👗 Rent the Runway Scraper
Scrape Rent the Runway (renttherunway.com) designer clothing and accessories by category...
👗 ZOZOTOWN
Scrape ZOZOTOWN (zozo.jp), Japan's largest fashion marketplace: name, brand, JPY price...
🥦 El Corte Inglés Scraper
Scrape El Corte Inglés elcorteingles.es products across fashion, electronics, home...

👉 Browse all abotapi scrapers

💬 Support

  • 🐞 Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
  • 🛠️ Need another site, extra fields or a private build? Email contact@abotapi.com.
  • ⭐ Enjoying it? A quick review on the actor page helps other users find it.