Target.com Product Scraper API
Pricing
from $0.78 / 1,000 product returneds
Target.com Product Scraper API
Scrape Target.com search and category listings plus product detail: TCIN, title, brand, price, promotions, ratings, shipping and pickup stock, images and URL.
Pricing
from $0.78 / 1,000 product returneds
Rating
0.0
(0)
Developer
Dami's Studio
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
6 minutes ago
Last modified
Categories
Share
Target.com Product Scraper
Pulls product data out of Target, the US retailer, as structured rows.
Type a search term, paste a category link, or paste a single product link. You get one row per product: TCIN, title, brand, the price Target is showing right now, whether it is marked down, any promotion attached to it, star rating and review count, whether it ships, whether it is on the shelf at a store you name, the image set, and the product URL.
No account, no API key, no cookies to paste. You put in words or links, you get rows.
A real row
This came back from a live run, trimmed only where the image list repeats:
{"tcin": "92084780","title": "Gourmia Digital 3qt Air Fryer with Guided Cooking Prompts Black/Stainless Steel Finish","brand": "Gourmia","url": "https://www.target.com/p/digital-3qt-air-fryer-with-guided-cooking-prompts-black-stainless-steel-finish/-/A-92084780","price": 39.99,"formattedPrice": "$39.99","regularPrice": 39.99,"comparisonPrice": null,"onSale": false,"savingsAmount": null,"savingsPercent": null,"unitPrice": null,"unitPriceSuffix": null,"priceType": "reg","priceNote": null,"pricedAtStoreId": "3991","promotions": [],"rating": 4.18,"reviewCount": 471,"onlineAvailability": "IN_STOCK","soldOut": false,"outOfStockInAllStores": false,"pickupAvailability": "IN_STOCK","pickupStoreId": "1375","pickupStoreName": "Mpls Nicollet Mall","pickupQuantity": 6,"scheduledDeliveryAvailability": "IN_STOCK","shipsBy": "2026-09-21","primaryImage": "https://target.scene7.com/is/image/Target/GUEST_6ec22cbf-b531-4468-86ce-f0194548211b","images": ["https://target.scene7.com/is/image/Target/GUEST_6ec22cbf-b531-4468-86ce-f0194548211b", "..."],"dpci": "072-04-6561","upc": null,"itemType": "Electric Fryers","departmentId": "72","classId": "4","categoryId": "ncrpx","highlights": ["3-quart air fryer can cook for one or a few","8 One-Touch Cooking Functions eliminate guesswork"],"specifications": ["Dimensions (Overall): 10.47 Inches (H) x 11.46 Inches (W) x 8.98 Inches (D)","Capacity (Volume): 3 Quart"],"description": null,"ratingDistribution": null,"searchTerm": "air fryer","position": 1,"scrapedAt": "2026-09-19T20:14:02.115Z"}
A sale row looks like this instead. onSale flips, and the old price and the saving come with it:
{"price": 2.69,"formattedPrice": "$2.69","regularPrice": 2.69,"comparisonPrice": 2.99,"onSale": true,"savingsAmount": 0.3,"savingsPercent": 10,"unitPrice": "$0.36","unitPriceSuffix": "/ounce","promotions": [{"message": "Buy 1 get 1 50% off M&M's, Reese's & more candy","promotionId": "941468854","type": "BOGO","thresholdType": "quantity","thresholdValue": 1,"rewardType": "PercentageOff","rewardValue": 50}]}
Input
Three ways in, and you can mix them in one run.
{"searchTerms": ["air fryer", "paper towels"],"maxItems": 200}
{"startUrls": ["https://www.target.com/c/air-fryers-kitchen-appliances/-/N-5xtg6","https://www.target.com/b/gourmia/-/N-qhfwe","https://www.target.com/p/-/A-92084780"],"maxItems": 100}
Add a postcode and the prices and the pickup stock change to a real shop instead of Target's online default:
{"searchTerms": ["milk", "bread"],"zipCode": "55403","maxItems": 50}
| Field | What it does |
|---|---|
searchTerms | One search per line. Every product the search returns becomes a row. |
startUrls | Target search, category, brand or product links. Product links always come back with the long description. |
maxItems | Hard cap on rows across everything above. This is what bounds the bill. |
zipCode | Five-digit US postcode. Prices and pickup stock come from the nearest store. |
includeAvailability | On by default. Stock for every row. One extra request per 30 products. |
includeFullDetail | Off by default. Long description and the star-by-star review split, at one extra request per product. |
proxyConfiguration | Leave it alone unless you need a specific network. |
Pickup stock needs a postcode
Without zipCode you get Target's online view: onlineAvailability, soldOut,
scheduledDeliveryAvailability and shipsBy are filled, and the three pickup fields come back
null. That is not a gap in the data, it is Target answering as a shopper who has not picked a
store.
Set zipCode and the run resolves the nearest shop once, then pickupAvailability,
pickupStoreId, pickupStoreName and pickupQuantity fill in, pickupQuantity being the
number of units that store says it has. Prices move too: pricedAtStoreId changes from 3991,
Target's online store number, to the real shop's, and grocery prices in particular are not the
same in both.
How many products you can get
Target stops any single search or category at 1,227 products: 1,199 as a starting offset plus a final page of 28. That is its limit, not the scraper's. If you need deeper coverage of a big category, split it: search the sub-categories separately, or narrow the term.
maxItems goes up to 2,000 across a whole run, so several searches in one go can exceed 1,227
in total.
Pricing
You are charged per product row. Nothing else bills.
- Sample rows and diagnostic rows are free. If you start a run with nothing filled in, you get one row explaining what to put where, and it costs nothing.
- A term Target stocks nothing for writes a free diagnostic row. See below, because this one is worth understanding.
- A product link that Target no longer recognises writes a free diagnostic row.
- A run that is refused and retried still costs nothing beyond the products it actually delivered.
maxItems is the ceiling on the bill, so set it to what you are willing to pay for.
Searching for something Target does not sell
Target never answers a search with "no matches". Ask it for "uranium hexafluoride" and it returns HTTP 200, a page of 28 products, and a total of 206, none of which have anything to do with the question. Handing those over would bill you for noise, so the first page of every keyword search is checked against the words you searched for, and if essentially none of the results mention any of them you get a free diagnostic row instead of 28 charges.
The check was calibrated on 66 real shopping terms and 12 that Target stocks nothing for. None of the 66 real terms was rejected, including awkward ones like "bed sheets", where the products are all titled "Sheet Set", and "sous vide immersion circulator". It is deliberately loose in the other direction: a term like "aircraft turbine blade" gets through, because Target genuinely sells things with "blade" in the title and dropping a real result is worse than passing on a weak one.
Category and brand links skip this check entirely, since there is no query to compare against.
What this does not do
Worth reading before you buy.
- Review text. You get the star average, the review count, and with
includeFullDetailthe count at each star. The written reviews themselves are a different data set and are not here. - Stock at more than one store. Pickup stock is for the single nearest store to the postcode you gave. Asking "which of these 40 shops has it" is a different job.
- Variants as separate rows. A shirt in six colours is one row, the one Target shows in the listing. Sizes and colours are not expanded.
- Anything behind a sign-in. Circle member pricing, your order history, cart behaviour. None of that is reachable and none of it is attempted.
- Non-US Target. This is target.com. Target Australia is a different company entirely.
upcon listing rows. The barcode only exists on the product's own page data, so it is filled whenincludeFullDetailis on or when you pasted a product link, andnullotherwise. Same fordescriptionandratingDistribution.- Sponsored placements. Paid ad slots inside Target's search results are skipped. You get the catalogue, not the ads. If you specifically want to study ad placements, this is the wrong tool.
Things that will trip you up
Target's prices move. The price in a row is what target.com was showing at scrapedAt, for
the store in pricedAtStoreId. Two runs an hour apart can honestly disagree.
regularPrice is not always the "before" price. When something is marked down, Target puts
the old price in comparisonPrice and leaves regularPrice equal to the current one. Read
onSale first, then comparisonPrice.
A category link is a node id. https://www.target.com/c/anything/-/N-5xtg6: the 5xtg6 at
the end is what matters and the words before it are decoration. Brand pages use the same shape,
so /b/gourmia/-/N-qhfwe works too.
Searching a very broad word is slower than it looks. "shoes" has tens of thousands of matches
and pages 28 at a time, so a 1,000-row run is 36 requests. maxItems is your friend.
FAQ
Does this need a Target account or an API key? No. Nothing is logged in, nothing is stored, and there is no key to obtain.
Can I scrape a whole category? Up to 1,227 products of it, which is Target's own ceiling. Beyond that, split the category.
Can I get prices for my local store?
Yes. Set zipCode. The run finds the nearest shop and prices against it. Grocery and seasonal
items are where you see the difference most.
How do I monitor a fixed list of products?
Put their product links in startUrls and schedule the run. Each link returns one row with the
full description, price, promotion and stock. TCINs are stable, so the rows line up run to run.
What is a TCIN?
Target's own product number: the digits after A- in a product URL. It is the id you want as a
join key. dpci is Target's internal shelf number and is useful in stores; upc is the
manufacturer's barcode, when Target publishes one.
Why is pickupQuantity sometimes null while pickupAvailability says IN_STOCK?
Target does not publish a unit count for every item. The status is the reliable field; the count
is a bonus when it is there.
Does it get blocked? It handles refusals itself: a refused request is retried on a different route, and if a search genuinely cannot be completed you get a free diagnostic row saying so rather than a silent empty result. Measured on 24 varied searches on 2026-09-19, every one returned products.
What happens if I give it a bad URL? A free diagnostic row naming the URL and showing the three shapes that do work. The run carries on with everything else and exits normally.
I searched something and got a diagnostic row instead of products. Why?
Target had nothing matching and answered with unrelated items, so they were left out rather than
billed to you. The row carries the term and a relevance score. If you think it was wrong, a
category or brand link fetches the same products with no check applied.
Output fields
| Field | Notes |
|---|---|
tcin | Target's product number. The join key. |
title, brand, url | url is Target's own canonical link for the product. |
price, formattedPrice, regularPrice, comparisonPrice | comparisonPrice is the "was" price on a markdown. |
onSale, savingsAmount, savingsPercent | Filled when Target is showing a was/now price. |
unitPrice, unitPriceSuffix | Grocery and household items, e.g. $0.36 /ounce. |
priceType, priceNote, pricedAtStoreId | Which store the price is for. 3991 means online. |
promotions[] | message, promotionId, type, thresholdType, thresholdValue, rewardType, rewardValue. |
rating, reviewCount | Star average and how many reviews it is from. |
ratingDistribution | Counts per star. Needs includeFullDetail or a pasted product link. |
onlineAvailability, soldOut, outOfStockInAllStores | Shipping view. |
pickupAvailability, pickupStoreId, pickupStoreName, pickupQuantity | Needs zipCode. |
scheduledDeliveryAvailability, shipsBy | Same-day delivery status and the latest ship date. |
primaryImage, images[] | Full-resolution image URLs. |
dpci, upc | Shelf number and barcode. upc needs full detail. |
itemType, departmentId, classId, categoryId | Target's own classification. |
highlights[], specifications[] | The bullets from the product page, with the markup stripped. |
description | The long copy. Needs full detail. |
searchTerm, position, scrapedAt | Which search produced the row, where it ranked, and when. |
Rows that are not products carry _sample: true or _diagnostic: true and charged: false, so
you can filter them out with one check.