CVS API endpoint
Returns one page of a CVS.com OTC (over-the-counter) retail category, subcategory, or brand page's product grid: products with title, brand, image, current/original price, and sponsored/featured/new-product flags; the total result count; and the facets (brand, color, size, price range, and other category-specific attributes, each with its selectable values and result counts) available to filter the page further. Covers the non-prescription retail catalog only. path is the segment of a page URL after "/shop/", e.g. "beauty" (top-level category), "health-medicine/allergy-sinus" (subcategory), or "brand-shop/s/safe-home" (brand page); a full https://www.cvs.com/shop/... URL or a "/shop/..." path is also accepted. Any of these can also carry an optional facet-filter suffix in the site's own URL shape, e.g. "beauty/makeup/eyes/q/CoverGirl/Black/brpc" to filter to brand CoverGirl and color Black -- see the response's facets field for which values/type codes a given category supports; filter values are case-sensitive exactly as the site renders them. page is a 1-indexed page number (default 1). sort is an optional result order matching the site's own Sort By control. CVS.com is only available from US and US-territory locations; a request served from an unsupported region returns an upstream error rather than an empty result.
/cvs/categoryReturns one page of a CVS.com OTC (over-the-counter) retail category, subcategory, or brand page's product grid. Covers the non-prescription retail catalog only — this does not cover prescription items, pharmacy ordering, refills, or any patient-specific data.
path is required. It is the segment of a page URL after /shop/, one of three base shapes: a top-level category (beauty, household, health-medicine), a nested subcategory (health-medicine/allergy-sinus), or a brand page (brand-shop/s/safe-home) — all three render through the same product grid. A full https://www.cvs.com/shop/... URL or a /shop/... path is also accepted.
Any of the three base shapes above can also carry an optional facet-filter suffix in CVS's own URL shape: {base}/q/{value}/{typeCode} for one filter (e.g. beauty/nails/q/essie/br filters to brand "essie"), or {base}/q/{value1}/{value2}/{typeCode1}{typeCode2} to combine two filters (e.g. beauty/makeup/eyes/q/CoverGirl/Black/brpc filters to brand "CoverGirl" and color "Black"). The response's facets field (or the live category page's own filter sidebar) is the discovery mechanism for which values and type codes a given category actually supports — this is not a fixed enum, it varies per category and is not hardcoded by this endpoint. Filter values are case-sensitive exactly as CVS's own site renders them (e.g. CoverGirl, not covergirl); an incorrect case silently returns a real, but empty, result rather than an error.
sort is optional, matching CVS's own category-page Sort By control; default is the site's own relevance order. One of: pa (Price Low to High), pd (Price High to Low), tr (Top Rated), rc (Most Reviewed), az (Name A-Z), za (Name Z-A). A sorted request costs one additional upstream round trip compared to the default (unsorted) request, so expect slightly higher latency when sort is set.
Notable response behavior:
list_price/sale_price/currency come from the page's own pricing data; a product with no price omits these fields.is_sponsored, is_featured, and is_new_product reflect the merchandising flags the category page itself carries.facets lists every filter the current category/filter state exposes: key is the upstream facet field name (e.g. brand, e_color, d_priceBucket), label is its display name (e.g. Brand, Color, Price), and values is a list of {name, count} — count is the number of results selecting that value would produce given whatever filters, if any, the request already applied. The set of facets and their values is category-specific and upstream-controlled; read it from a live response rather than assuming a fixed set.503 upstream error rather than an empty or wrong result.path (including a malformed filter suffix) or an unrecognized sort value returns a 400 invalid-parameter error before any upstream request is made.| Field | Filled in, of 20 checked | Values in the sample |
|---|---|---|
| id | 20 | |
| title | 20 | “DAISE Foaming Body Wash, Vanilla Whip, 8.8 OZ” and 19 other values |
| url | 20 | cvs.com |
| brand | 20 | “DAISE” and 9 other values |
| image_url | 20 | cvs.com |
| currency | 20 | USD in all 20 |
| list_price | 20 | 2.99 to 16.49, median 6.59 |
| sale_price | 20 | 2.99 to 12.99, median 5.49 |
| is_new_product | 7 | true in 7 of 7 |
| Parameter | Type | Required | Default | Description | Example |
|---|---|---|---|---|---|
| path | string | Yes | CVS category, subcategory, or brand-page URL path, optionally with a /q/{value}/{typeCode} facet-filter suffix, e.g. \ | beauty | |
| page | integer | No | 1-indexed page number, default 1 | 1 | |
| sort | string | No | Result sort order, default the site's own relevance order. One of pa (Price Low to High), pd (Price High to Low), tr (Top Rated), rc (Most Reviewed), az (Name A-Z), za (Name Z-A) Allowed values: pa, pd, tr, rc, az, za. | pa | |
| x-api-key (header) | string | Yes | API key required |
curl -X GET "https://api.crawlora.net/api/v1/cvs/category?path=beauty&page=1&sort=pa" \ -H "x-api-key: $CRAWLORA_API_KEY"
{
"code": 200,
"msg": "OK",
"data": {
"total_count": 8766,
"page": 1,
"products": [
{
"id": "478253",
"title": "Crest Pro-Health Breath Mist, Clean Mint, 0.44 OZ, 2 PK",
"url": "https://www.cvs.com/shop/crest-pro-health-breath-mist-clean-mint-0-44-oz-2-pk-prodid-478253",
"brand": "Crest",
"image_url": "https://www.cvs.com/bizcontent/merchandising/productimages/high_res/72894700032.jpg",
"currency": "USD",
"list_price": 4.99,
"sale_price": 4.99
}
],
"facets": [
{
"key": "brand",
"label": "Brand",
"values": [
{
"name": "Crest",
"count": 12
},
{
"name": "one+other",
"count": 3
}
]
},
{
"key": "d_priceBucket",
"label": "Price",
"values": [
{
"name": "$0 - $5",
"count": 9
},
{
"name": "$5 - $10",
"count": 6
}
]
}
]
}
}Request schema
No body schema
Response schema
#/definitions/cvs.categoryResponseDoc
| Field | Type | Required | Enum | Bounds | Example | Description |
|---|---|---|---|---|---|---|
| code | integer | No | 200 | |||
| data | cvs.CategoryResponse | No | ||||
| data.facets | array | No | CategoryFacet record, 5 fields: key, label, values. Described under Search CVS OTC products by keyword API. | |||
| data.page | integer | No | 1 | |||
| data.products | array | No | CategoryProduct record, 11 fields: brand, currency, id, image_url, is_featured, is_new_product, is_sponsored, list_price, sale_price, title, url. Described under Search CVS OTC products by keyword API. | |||
| data.total_count | integer | No | 8766 | |||
| msg | string | No | OK |
| Status | Description | Schema |
|---|---|---|
| 400 | Bad Request | #/definitions/app.Response |
| 429 | Too Many Requests | #/definitions/app.Response |
| 503 | Service Unavailable | #/definitions/app.Response |
Use environment variables for secrets and keep Crawlora API keys server-side.
curl -X GET "https://api.crawlora.net/api/v1/cvs/category?path=beauty&page=1&sort=pa" \
-H "x-api-key: $CRAWLORA_API_KEY"