Scrape Kohl's prices, sale ladders and store stock
Regular price, sale price, the promotion that applies, Kohl's Cash eligibility and pickup availability by ZIP from kohls.com. No browser.
Measured on Crawlbase
99.0% success in August 2026. Kohl's sits in the complex tier: it challenges plain fetches, and Crawlbase clears that for you, which is why a page costs two credits and still needs no browser on your side. 1.3% of successful calls used the JavaScript token.
The call
# Product page, rendered HTML curl "https://api.crawlbase.com/?token=YOUR_TOKEN&country=US&url=https%3A%2F%2Fwww.kohls.com%2Fproduct%2Fprd-6248533%2Fsonoma-goods-for-life-mens-supersoft-crewneck-tee.jsp" # Same page, stock for the store nearest a ZIP curl "https://api.crawlbase.com/?token=YOUR_TOKEN&country=US&cookies=zipCode%3D60601&url=https%3A%2F%2Fwww.kohls.com%2Fproduct%2Fprd-6248533%2Fsonoma-goods-for-life-mens-supersoft-crewneck-tee.jsp"
from crawlbase import CrawlingAPI api = CrawlingAPI({'token': 'YOUR_TOKEN'}) r = api.get('https://www.kohls.com/product/prd-6248533/sonoma-goods-for-life-mens-supersoft-crewneck-tee.jsp', {'country': 'US', 'cookies': 'zipCode=60601'}) html = r['body'] # prices live in the productV2JsonData script tag
const { CrawlingAPI } = require('crawlbase'); const api = new CrawlingAPI({ token: 'YOUR_TOKEN' }); const r = await api.get('https://www.kohls.com/product/prd-6248533/sonoma-goods-for-life-mens-supersoft-crewneck-tee.jsp', { country: 'US', cookies: 'zipCode=60601' }); const state = JSON.parse(r.body.match(/productV2JsonData\s*=\s*(\{.*?\});/s)[1]);
Parameters that matter
| Parameter | Set it to | Why |
|---|---|---|
country | US | Kohl's serves a blocking page to non-US exits. Set it on every call. |
javascript | leave unset | Prices, the sale ladder and the promo text are in a JSON blob in the HTML. Almost every successful call in the measured month ran without a browser. |
cookies | zipCode=<zip> | Sets the store used for pickup availability. Without it you get the national default, which is not a stock answer. |
autoparse | not yet | No dedicated scraper. The embedded JSON is stable and the fields below map straight from it. |
Fields you get, from the embedded JSON
stringstringnumbernumber | nullstringbooleanstringstringobjectnumberWhat breaks, and the fix
WS=, not by page number. The offset is the count of items already seen, in steps of 48. A wrong step returns page one again and you will believe the category is 48 items long.Run it on a schedule
A daily price watch over 50,000 products is 100,000 credits a day at two credits a page. Use the Crawler so bursts are smoothed and pass the ZIP as a cookie per job when you track stock per store.
Questions
Why does a Kohl's page cost two credits?
Kohl's is in the complex tier. Crawlbase clears its bot challenge for you; the price reflects that work, and it still needs no browser.
Can I get store stock?
Yes. Pass cookies=zipCode=<zip> and read storeAvailability from the embedded JSON.