BJ's
BJ's Wholesale Club price range (not a club price), rating, brand when given and national availability flags, by item number, about 4 million products per credit. Search too. Prescription items are never returned.
BJ's Wholesale Club price range (not a club price), rating, brand when given and national availability flags, by item number, about 4 million products per credit. Search too. Prescription items are never returned.
At a glance
Property | Value |
|---|---|
|
|
Product id | The BJ's item number, 3 to 8 digits ( |
Marketplaces | Live: |
Tier |
|
Ids per call | 100 |
Typical call | 1–3 s for 100 ids |
Search |
|
There is no price, only a range
BJ's data gives a price range, not the price at a given club. price is always null, and the current club price is not available. The range (bjs.minPrice and bjs.maxPrice) is not a price: on BJ's own pages it matched the low end for some items, the high end for others, and neither for some. Items whose price shows only after sign-in carry bjs.priceAfterSignIn: true, and their range may not reflect what a member pays.
Example
- cURL
- Python
- Node.js
curl -X POST "https://api.scrapelyserp.com/v1/products" \
-H "Authorization: Bearer $SCRAPELY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"platform":"bjs","ids":["335416","328157"]}'import os
import requests
HEADERS = {"Authorization": f"Bearer {os.environ['SCRAPELY_API_KEY']}"}
r = requests.post(
"https://api.scrapelyserp.com/v1/products",
headers=HEADERS,
json={"platform": "bjs", "ids": ["335416", "328157"]},
timeout=30,
)
r.raise_for_status()
data = r.json()
for p in data["results"]:
print(p["id"], p["status"], p["bjs"]["minPrice"], p["bjs"]["maxPrice"])const res = await fetch('https://api.scrapelyserp.com/v1/products', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.SCRAPELY_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ platform: 'bjs', ids: ['335416', '328157'] }),
signal: AbortSignal.timeout(30_000),
});
if (!res.ok) throw new Error((await res.json()).error.code);
const data = await res.json();
for (const p of data.results) console.log(p.id, p.status, p.bjs?.minPrice, p.bjs?.maxPrice);Full reference → POST /v1/products
BJ's fields
Besides the common fields, each result carries a bjs object. price is null on every BJ's result; availability is left out.
Field | Description |
|---|---|
| The low and high end of the price range in BJ's data. A range, not a price; |
| True when BJ's shows the item's price only after sign-in. The range may then not reflect what a member pays. |
| Average review rating in half stars (0 to 5, not exact) and the number of reviews; |
| The brand when BJ's data names one, else |
| BJ's national flags: not a stock count and not any one club's stock, and they can disagree with each other (an item can be flagged out of stock and still available). No club is chosen. |
| True when BJ's marks the item as alcohol; |
Statuses on BJ's
partial: BJ's answered without a title. Ask again later.not_found: BJ's has no such item number. Prescription items are never returned and read the same way.unavailable: no usable answer after retries. Not charged; ask again.