PetSmart Product, Price & Promo Scraper (US) avatar

PetSmart Product, Price & Promo Scraper (US)

Pricing

from $1.95 / 1,000 product scrapeds

Go to Apify Store
PetSmart Product, Price & Promo Scraper (US)

PetSmart Product, Price & Promo Scraper (US)

PetSmart scraper: search terms or category, brand and offer pages to one row per product with USD price, list price, discount, price range across sizes, running promotions, rating, reviews, Autoship flag, brand and image. For pet-supply price and promo watching.

Pricing

from $1.95 / 1,000 product scrapeds

Rating

0.0

(0)

Developer

Superslow Sloth

Superslow Sloth

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

1

Monthly active users

8 days ago

Last modified

Share

Search PetSmart (the US pet retailer) by keyword, or read a category, brand or new-arrivals page, and get one flat row per product: the current price and the list price in USD, the discount in dollars and percent, the lowest and highest price across the product's sizes, the promotions currently running on it (Autoship offers, code offers, shipping and loyalty messages), rating and review count, brand, category, pet type, the product link and the photo. Run it on a schedule and diff the dataset to get a pet-supply price and promo watch: which foods, litters and treats dropped in price, and which only advertise an Autoship discount or a code.

No account, no API key, no login, no browser. One request returns 40 products.

Input

FieldNotes
searchTermsOne or more search terms, one per line (cat food, dog dental chews, kong). A brand name such as royal canin or friskies is sent by the site to that brand's page and that whole list is read; any other term is read as search results. A product found by two terms is returned once, under the first.
startUrlsPetSmart pages to read in full: a category (/dog/food/, /cat/food-and-treats/dry-food/), a brand (/featured-brands/royal-canin/) or a collection (/new-and-featured/f/pet/cat). A filter kept in the address (?brand=Royal+Canin) is kept on every page. A search URL (/search/?q=...) is read as that search term. The page must list products; the home page, /sale/ and /store-locator/ list none and fail with a message. Give terms, URLs or both.
maxItemsProducts to read per term or page (default 100, up to 10,000). 40 per page.
onlyOnSaleReturn only products whose current price is below the list price. Products that are not reduced are read, not returned and not charged.
sortrelevance (default), best-sellers, price-asc, price-desc, new-arrivals, top-rated: the choices of the site's own sort menu. See the depth note below: only relevance goes past 1,000 products.
proxyConfigurationApify datacenter proxy by default.

Example input:

{
"searchTerms": ["cat food", "dog dental chews"],
"startUrls": [{ "url": "https://www.petsmart.com/dog/food/" }],
"maxItems": 120,
"onlyOnSale": true,
"sort": "price-asc"
}

Output

Prices are numbers in US dollars; currency is the currency the page states (USD on every page measured).

FieldNotes
query, positionThe search term or page URL that first found the product, and its place in the site's list for that source and sort (1 is first).
product_id, master_product_id, urlPetSmart's item number (5209028), the number of the product page it belongs to (20995; sizes and flavors of one product share it) and the product link. url comes from the page's structured data and is null if the page did not send it.
name, brandAs the page shows them (HTML entities decoded).
category, categories, pet_typesThe primary category (Dry Food), the category list the site files it under, and the pets it is for (Cat, Dog, ...).
price, original_priceprice is the price now. original_price is the list price. They are equal when the product is not reduced. Both are the price of the product's default size, see below.
on_sale, discount_amount, discount_percenton_sale is true when price is below original_price. discount_amount is the dollars off and discount_percent is worked out from the two prices (one decimal place). Both are null when the product is not on sale, never 0.
price_min, price_maxThe lowest and highest price across the product's sizes and flavors, the figures behind the card's "$15.58 - $28.59". Equal for a product with one price.
promotions, promo_textThe promotions PetSmart attaches to the product that are running now, in the site's own order. Each has text, type (autoship or null), discount (35% or null), starts and ends (ISO times or null). promo_text is the first one's text. An empty list and a null promo_text mean none.
variationsThe card's variation labels, e.g. ["3 Sizes", "1 Flavor"].
rating, review_countAverage star rating and number of reviews. Null for a product with no reviews.
autoship_eligibleTrue if the product can be put on Autoship (repeat delivery).
in_store_only, online_onlyThe site's availability flags. Null when the page does not send the flag, which is common: null is not false.
discontinuedTrue for a product the site marks discontinued. Null for the rest (the page only sends the flag on some).
upcThe barcode number where the page sends one.
image_urlThe product photo.

Example row (real values, 2026-10-16):

{
"query": "cat food",
"position": 5,
"product_id": "5209028",
"master_product_id": 20995,
"name": "Hill's® Science Diet® Perfect Weight Adult Dry Cat Food - Chicken",
"brand": "Hill's Science Diet",
"url": "https://www.petsmart.com/cat/food-and-treats/dry-food/hills-science-diet-perfect-weight-adult-dry-cat-food---chicken-20995.html",
"image_url": "https://s7d2.scene7.com/is/image/PetSmart/5209028?$sclp-prd-main_large$",
"category": "Dry Food",
"categories": ["Dry Food"],
"pet_types": ["Cat"],
"currency": "USD",
"price": 69.99,
"original_price": 71.99,
"on_sale": true,
"discount_amount": 2.0,
"discount_percent": 2.8,
"price_min": 24.99,
"price_max": 69.99,
"promotions": [
{ "text": "Earn $10 back in savings (5,000 points) when you spend $39+ with Free Same-Day Delivery thru 10/18. One-time use.", "type": null, "discount": null, "starts": "2026-10-13T09:30:00.000Z", "ends": "2026-10-19T09:30:00.000Z" },
{ "text": "Get 40% OFF your 1st Hill's Autoship order, 20% OFF your 2nd & 10% OFF your 3rd. Place your first order by 10/31.", "type": "autoship", "discount": "40%", "starts": "2026-10-02T09:30:00.000Z", "ends": "2026-11-01T09:30:00.000Z" },
{ "text": "Save an additional 20% on your 1st Autoship order of select dog & cat food with code: EXTRA20", "type": null, "discount": null, "starts": "2026-10-08T09:30:00.000Z", "ends": "2026-10-20T09:30:00.000Z" },
{ "text": "Free Same-Day Delivery, No Order Minimum!", "type": null, "discount": null, "starts": null, "ends": null },
{ "text": "Sign In & Enjoy Free Shipping Over $49", "type": null, "discount": null, "starts": "2026-02-03T23:00:00.000Z", "ends": null }
],
"promo_text": "Earn $10 back in savings (5,000 points) when you spend $39+ with Free Same-Day Delivery thru 10/18. One-time use.",
"variations": ["3 Sizes", "1 Flavor"],
"rating": 4.5,
"review_count": 1144,
"autoship_eligible": true,
"in_store_only": false,
"online_only": false,
"discontinued": null,
"upc": "052742297002"
}

What the price fields mean

PetSmart sells one product in several sizes. The page gives the product a default size with a list price and a current price, and a range across all sizes. price and original_price are the default size's two prices (they are the current and list figures the page sends, and the card's price text agrees with them on every product measured: 960 products checked). price_min and price_max are the card's range. In the example, the 24.99 to 69.99 range comes from sizes of the same food; the default size costs 69.99, so price_max equals price here. That is common but not a rule (the default size was the top of the range on 267 of the 342 ranged products measured). To compare one size over time, join on product_id and watch price.

An Autoship or code offer is not a reduction. "Save 35% on your first Autoship order" and "with code: EXTRA20" do not change the shelf price: price does not include them, and on_sale stays false when the product is not otherwise reduced. They are in promotions. Filter on

promotions[].type == "autoship"
or on the text to see them, on on_sale for shelf reductions.

Promotions: what is in the list

The site attaches to every product its store-wide messages ("Free Same-Day Delivery, No Order Minimum!", "Sign In & Enjoy Free Shipping Over $49", loyalty-point offers) as well as product-specific ones, so the list is rarely empty. The page also still sends promotions whose end date has passed and promotions with no text (price steps of the Autoship program). The actor drops both: a promotion is kept only if it has text and is running at the time the page was served (judged on the page's own clock). Check starts and ends to see how long an offer lasts.

Honest nulls

A field the page did not send is null, never 0 or "".

  • No rating (rating, review_count null) means the product has no reviews.
  • in_store_only and online_only are null when the page omits the flag. Do not read null as false.
  • url is null if the page's structured data did not list the product.
  • discontinued is only ever true or null.

Pricing

Pay per event:

  • $0.002 per run (actor-start), charged only after your input is validated, so a run that fails on bad input costs nothing.
  • $0.00195 per product row written (product-scraped), i.e. $1.95 per 1,000 products. A row that is not written is not charged: rows filtered by onlyOnSale, and repeats of a product another term already returned, are free.

How it fetches

It reads the product list that petsmart.com's own pages embed: the first answer of the site's search engine, as JSON in the page, plus the page's structured data for the product links. Measured 2026-10-16: HTTP 200 from a plain home connection and from an Apify datacenter address, no key or cookie needed. A refusal (403, 429, 5xx), a 200 that is not a PetSmart product list, or a dropped connection is treated as the address being blocked, and the actor rotates to a fresh one and retries. No refusal page was ever served while this was built, so that path is tested against a stand-in, not a recorded page.

Things worth knowing, all measured:

  • A page is about 1.5 MB and takes 2 to 4 seconds. A run of 1,000 products is 25 pages, around 40 MB of proxy traffic.
  • Depth depends on the sort. relevance goes up to 250 pages, which is 10,000 products (a search matching 16,912 products answered page 250 and refused page 251). Every other sort stops at 25 pages, 1,000 products, however many match (cat food matches 3,478; its price-descending page 26 is empty). The log says so when a list was cut short, and the run summary names those sources. To see more than 1,000 in price order, narrow the search or use a category page.
  • Category and brand pages default to best sellers, which is a sorted list and so also stops at 1,000 (/dog/food/ has 1,810). The actor always sends the sort you chose (relevance unless you set another), so a category read with the default settings reads the whole list.
  • A sort the site does not know is ignored, not refused. The site answers a misspelled sort with relevance order and HTTP 200. The actor sends only the values of the site's own menu and checks which list answered each page; if it is not the one asked for, that source fails with "sort was ignored" instead of returning the wrong order.
  • A brand name is redirected. royal canin, friskies, blue buffalo and hill's science diet are sent by the site to /featured-brands/<brand>/, and the redirect drops the sort and the page. The actor reads that brand page, again with your sort, and continues from there; the run log names the page. query stays the term you typed. Most other terms (cat food, litter with a sort, purina) are answered in place as search results.
  • Terms are cleaned. Spaces at the start and end and doubled spaces change the site's result count (cat food finds 3,219 and cat food 3,478), so the actor trims and collapses them. Case does not matter.
  • A search with no match is not an error. The site answers it with HTTP 404 and no products; the actor reports "no results" in the log and returns nothing for that term, at no charge. A page that does not exist (an unknown category path) is also HTTP 404, but its body is the site's whole default list; the actor treats that as a missing page and fails the source.
  • Not offered. The site's facet filters are not inputs. A filter kept in a start URL's address (?brand=Royal+Canin) is honoured by the site and kept by the actor; start from a page that already narrows the list.
  • No stock levels. Product pages hold the stock; the list pages do not, so the rows say nothing about availability beyond in_store_only and online_only.