Kroger API endpoint
Use Crawlora's Kroger search API to extract supported public Kroger data as structured JSON. This page includes request parameters, cURL examples, response schema, error behavior, credit cost, and a Playground link for testing before integration.
/kroger/searchSearches Kroger products by keyword and returns normalized product cards (price, unit price, brand, size, stock level) plus the facet groups Kroger offers for the query (brands, nutrition, savings, price range and more). Served from Kroger's own search JSON API with real upstream pagination; if that path is unavailable it falls back to parsing the rendered search page, and the source field reports which path answered. Facet filters and sort apply to the JSON path only: when any of them is set, a JSON-path failure returns an error rather than silently falling back to unfiltered results. Developers commonly use this endpoint for data enrichment, monitoring, research dashboards, internal automation, and agent-native workflows that need repeatable structured public web data. Authentication uses the documented Crawlora headers, and usage is metered with the credit cost shown on this page.
Request parameters are generated from the active endpoint catalog. Required values must be sent before Crawlora can call the upstream public web data source.
| Parameter | Type | Required | Default | Description | Example |
|---|---|---|---|---|---|
| query | string | Yes | Search keyword | ||
| page | integer | No | One-based result page Minimum: 1. | ||
| sort | string | No | Result order. One of: relevance, name_asc, popularity_desc Allowed values: relevance, name_asc, popularity_desc | ||
| brands | string | No | Comma-separated brand names to filter by, taken verbatim from a previous response's facets | ||
| nutrition | string | No | Comma-separated nutrition/dietary facet values | ||
| flavor | string | No | Comma-separated flavor facet values | ||
| scent | string | No | Comma-separated scent facet values | ||
| savings | string | No | Comma-separated savings facet values | ||
| more_options | string | No | Comma-separated more-options facet values | ||
| price_min | number | No | 0 | Lower bound of the price filter; defaults to 0 | |
| price_max | number | No | Upper bound of the price filter; required to filter on price | ||
| x-api-key (header) | string | Yes | API key required |
curl -X GET "https://api.crawlora.net/api/v1/kroger/search?query=coffee&page=1&sort=relevance" \ -H "x-api-key: $CRAWLORA_API_KEY"
Send your scraping API key in the x-api-key header. Use the console API Keys page to rotate or select the active key.
Endpoint usage is metered in credits. The plan prices, included credits, limits, and overage rates below match the active backend billing configuration.
| Plan | Price | Included credits | Daily cap | Rate limit | Overage |
|---|---|---|---|---|---|
| Free | $0/mo | 2,000 | 500 daily credits | 5/min | No overage |
| Starter | $9/mo | 20,000 | 5,000 daily credits | 15/min | $0.75/1,000 overage credits when enabled |
| Growth | $29/mo | 100,000 | 25,000 daily credits | 45/min | $0.45/1,000 overage credits when enabled |
| Pro | $79/mo | 400,000 | No daily cap | 120/min | $0.30/1,000 overage credits |
| Business | $199/mo | 1,200,000 | No daily cap | 300/min | $0.20/1,000 overage credits |
| Enterprise | $499/mo | 5,000,000 | No daily cap | 1,000/min | $0.12/1,000 overage credits |
This endpoint is executed through Crawlora's managed scraping infrastructure.
Some targets require real browser execution because the data is loaded through JavaScript, dynamic rendering, or interaction-like browser behavior.
For supported endpoints, Crawlora can route requests through a managed browser cluster. This allows Crawlora to execute JavaScript, load dynamic content, apply browser-level request behavior, and normalize the rendered result into JSON.
You do not need to operate your own Playwright, Puppeteer, Chrome, proxy, queue, or retry infrastructure.
- **Filters and sort apply to the `json_api` path only.** When any of them is set and that path fails, the request returns an error instead of falling back to the rendered page — the HTML path cannot honor these filters, so returning its unfiltered results would be wrong. Unfiltered requests still fall back as before. - Each result's `upc` is usable directly as the `upc` query parameter to [`/kroger/product`](kroger-product.md). - For browsing a specific product category instead of keyword search, see [`/kroger/category`](kroger-category.md), which returns results in this same shape. - `total_count` reflects the number of results Kroger's own page reports as loaded, not necessarily every result matching the query — Kroger's search page loads results in batches behind a "Load More Results" control. - `source` reports which upstream path served the response: `json_api` (Kroger's own search API, the primary path) or `html` (the rendered-page fallback, used only when the JSON path is unavailable). - **Pagination is real on the `json_api` path** — it uses Kroger's own page offset/size, and `has_more` reports whether further pages exist. On the `html` fallback `has_more` is always `false` and paging past page 1 remains best-effort. - `facets` lists the refinement groups Kroger offers for the query (brands, nutrition, savings, price range and more), each value with its result count. Only populated on the `json_api` path. - `brand` and `stock_level` are populated on the `json_api` path only; the rendered result cards carry neither. - A missing `query` returns `400` before any upstream request is made. Example response: ```json { "code": 200, "msg": "OK", "data": { "query": "edward & sons", "page": 1, "total_count": 37, "products": [ { "upc": "0004318200391", "url": "https://www.kroger.com/p/edward-sons-not-chick-n-bouillon-cubes/0004318200391?fulfillment=PICKUP&searchType=default_search", "title": "Edward & Sons® Not-Chick'n Bouillon Cubes", "image_url": "https://www.kroger.com/product/images/medium/front/0004318200391", "price": 2.99, "currency": "USD", "unit_price": "$1.20/oz", "size": "2.5 oz", "snap_ebt_eligible": true, "low_stock": false } ] } } ```
Crawlora does not silently return bad data when the upstream page cannot be used.
| Status | Common failure case |
|---|---|
| 400 | Invalid input or missing required parameter |
| 429 | Plan or endpoint rate limit exceeded |
| 500 | Internal execution error |
| 502 | Upstream platform failed, returned unusable HTML, or served a challenge page that could not be resolved |
When possible, Crawlora returns structured error context so your integration can retry, back off, or inspect the request.
| Status | Description | Schema |
|---|---|---|
| 400 | Bad Request | #/definitions/app.Response |
| 429 | Too Many Requests | #/definitions/app.Response |
| 503 | Service Unavailable | #/definitions/app.Response |
{
"code": 200,
"msg": "OK",
"data": {
"query": "edward & sons",
"page": 1,
"total_count": 37,
"products": [
{
"upc": "0004318200391",
"url": "https://www.kroger.com/p/edward-sons-not-chick-n-bouillon-cubes/0004318200391?fulfillment=PICKUP&searchType=default_search",
"title": "Edward & Sons® Not-Chick'n Bouillon Cubes",
"image_url": "https://www.kroger.com/product/images/medium/front/0004318200391",
"price": 2.99,
"currency": "USD",
"unit_price": "$1.20/oz",
"size": "2.5 oz",
"snap_ebt_eligible": true,
"low_stock": false
}
]
}
}Request schema
No body schema
Response schema
#/definitions/kroger.searchResponseDoc
| Field | Type | Required | Enum | Bounds | Example | Description |
|---|---|---|---|---|---|---|
| code | integer | No | 200 | |||
| data | kroger.SearchResponse | No | ||||
| data.facets | array | No | ||||
| data.facets[].group | string | No | ||||
| data.facets[].values | array | No | ||||
| data.facets[].values[].count | integer | No | ||||
| data.facets[].values[].name | string | No | ||||
| data.facets[].values[].slug | string | No | ||||
| data.has_more | boolean | No | HasMore reports whether Kroger says more results exist past this page. Only meaningful on the JSON-API path; false on the HTML fallback. | |||
| data.page | integer | No | ||||
| data.products | array | No | ||||
| data.products[].brand | string | No | Brand and StockLevel are populated by the JSON-API path only (the HTML result cards carry neither); both are omitted when the HTML fallback served the response. See Search's doc comment. | |||
| data.products[].currency | string | No | ||||
| data.products[].image_url | string | No | ||||
| data.products[].low_stock | boolean | No | ||||
| data.products[].original_price | number | No | ||||
| data.products[].price | number | No | ||||
| data.products[].size | string | No | ||||
| data.products[].snap_ebt_eligible | boolean | No | ||||
| data.products[].stock_level | string | No | ||||
| data.products[].title | string | No | ||||
| data.products[].unit_price | string | No | ||||
| data.products[].upc | string | No | ||||
| data.products[].url | string | No | ||||
| data.query | string | No | ||||
| data.source | string | No | Source is which upstream path served this response: "json_api" (the primary path) or "html" (the fallback). See Search's doc comment. | |||
| data.total_count | integer | No | ||||
| msg | string | No | OK |
Use environment variables for secrets and keep Crawlora API keys server-side.
curl -X GET "https://api.crawlora.net/api/v1/kroger/search?query=coffee&page=1&sort=relevance" \
-H "x-api-key: $CRAWLORA_API_KEY"Crawlora is designed for responsible structured public web data workflows. Customers are responsible for using Crawlora in compliance with applicable laws, third-party rights, target-platform rules, and Crawlora terms.
Read Crawlora terms