Grainger API: Search products
Searches Grainger industrial and facility supplies by words or Grainger item number and returns product details with public USD list prices in the order Grainger shows them. Words show the matching category, whose first 25 products are listed; an item number returns that product.
Unofficial. Not affiliated with or endorsed by Grainger.
Inputs
Values from the run on Nov 3, 2026, shown under Output.
- Query, required
query Product words or Grainger item number, such as safety glasses or 4VCH6.
safety glasses
- Max Results optional
max_results Maximum number of products, such as 12. Category pages may show only the first 25.
24 (default)
Whole number from 1 to 48.
Input as JSON
{ "query": "safety glasses"}Output
{ "products": [ { "brand": "EDGE EYEWEAR", "price": 49.73, "currency": "USD", "image_link": "https://static.grainger.com/rp/s/is/image/Grainger/20C472_AS01" , "price_unit": "each", "availability": "In Stock", "product_link": "https://www.grainger.com/product/EDGE-EYEWEAR-Safety-Glasses-Smoke-Lens-20C472" , "product_name": "EDGE EYEWEAR Safety Glasses: Smoke Lens, Full-Frame, Metal Detectable, White Frame, Brazeau Series", "key_attributes": [ { "name": "Series", "value": "Brazeau" }, { "name": "Lens Color", "value": "Smoke" }, { "name": "Frame Color", "value": "White" } ], "grainger_item_number": "20C472", "manufacturer_model_number": "TXB246" }, { "brand": "EDGE EYEWEAR", "price": 49.73, "currency": "USD", "image_link": "https://static.grainger.com/rp/s/is/image/Grainger/TXB236_FRNT_Brazeau__FZBH_v2" , "price_unit": "each", "availability": "In Stock", "product_link": "https://www.grainger.com/product/EDGE-EYEWEAR-Safety-Glasses-Smoke-Lens-20C473" , "product_name": "EDGE EYEWEAR Safety Glasses: Smoke Lens, Full-Frame, Metal Detectable, Black Frame, Brazeau Series", "key_attributes": [ { "name": "Series", "value": "Brazeau" }, { "name": "Lens Color", "value": "Smoke" }, { "name": "Frame Color", "value": "Black" } ], "grainger_item_number": "20C473", "manufacturer_model_number": "TXB236" }, { "brand": "PYRAMEX", "price": 55.13, "currency": "USD", "image_link": "https://static.grainger.com/rp/s/is/image/Grainger/23Y588_AS02" , "price_unit": "each", "availability": "In Stock", "product_link": "https://www.grainger.com/product/PYRAMEX-Safety-Glasses-Gray-Lens-23Y589" , "product_name": "PYRAMEX Safety Glasses: Gray Lens, Full-Frame, Scratch-Resistant, Black Frame, Goliath(R) Series", "key_attributes": [ { "name": "Series", "value": "Goliath(R)" }, { "name": "Lens Coating", "value": "Scratch-Resistant" }, { "name": "Lens Color", "value": "Gray" } ], "grainger_item_number": "23Y589", "manufacturer_model_number": "SB5621D" } ]}Code
curl https://api.fous.com/v1/runs \ -H "Authorization: Bearer $FOUS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"method":"grainger.com/search_products","input":{"query":"safety glasses"}}' # Save as fous.py, then run: python3 fous.pyimport json, os, timefrom urllib.error import HTTPErrorfrom urllib.request import Request, urlopenAPI = "https://api.fous.com/v1/runs" KEY = os.environ["FOUS_API_KEY"]HEADERS = { "Authorization": f"Bearer {KEY}", "Content-Type": "application/json" ,}def call(url, body=None): data = json.dumps(body).encode() if body else None request = Request(url, data, HEADERS) try: with urlopen(request, timeout=120) as r: return r.status, json.load(r) except HTTPError as error: message = json.load(error)["error"]["message"] raise RuntimeError(message) from errorstatus, run = call(API, { "method": "grainger.com/search_products" , "input": { "query": "safety glasses" }})# 202: still going after 30 s. Ask again until it ends.while status == 202: time.sleep(2) status, run = call(f"{API}/{run['id']}")print(json.dumps(run["data"], indent=2))// Save as fous.mjs, then run: node fous.mjsconst api = "https://api.fous.com/v1/runs" ;const headers = { Authorization: `Bearer ${process.env.FOUS_API_KEY}`, "Content-Type": "application/json" ,};let response = await fetch(api, { method: "POST", headers, body: JSON.stringify({ "method": "grainger.com/search_products" , "input": { "query": "safety glasses" } }), signal: AbortSignal.timeout(120_000),});let run = await response.json();// 202: still going after 30 s. Ask again until it ends.while (response.status === 202) { await new Promise((done) => setTimeout(done, 2_000)); response = await fetch(`${api}/${run.id}`, { headers }); run = await response.json();}if (!response.ok) throw new Error(run.error.message);console.log(run.data);# Connect your agent to Fous once, over MCP (Streamable HTTP):# https://api.fous.com/mcp# Set FOUS_API_KEY first: create a key at https://app.fous.com/keys.# Claude Codeclaude mcp add \ --scope user \ --transport http fous https://api.fous.com/mcp \ --header "Authorization: Bearer ${FOUS_API_KEY:?Set FOUS_API_KEY to your Fous API key}"# Codexcodex mcp add fous \ --url https://api.fous.com/mcp \ --bearer-token-env-var FOUS_API_KEY# Cursor, VS Code, Windsurf, Cline and morenpx -y add-mcp https://api.fous.com/mcp -g -n fous \ --header "Authorization: Bearer ${FOUS_API_KEY:?Set FOUS_API_KEY to your Fous API key}"# Then ask your agent:# "Use Fous to run grainger.com/search_products# with {"query":"safety glasses"}"Over HTTP, the answer’s data holds the output. A run still going after 30 seconds answers 202 with its id: ask GET /v1/runs/{id} until it ends.
Schema
Input schema
{ "type": "object", "required": [ "query" ], "properties": { "query": { "type": "string", "description": "Product words or Grainger item number, such as safety glasses or 4VCH6." }, "max_results": { "type": "integer", "default": 24, "maximum": 48, "minimum": 1, "description": "Maximum number of products, such as 12. Category pages may show only the first 25.", "x-fous-developer": true } }, "additionalProperties": false}Output schema
{ "type": "object", "required": [ "products" ], "properties": { "products": { "type": "array", "items": { "type": "object", "required": [ "product_name", "brand", "grainger_item_number", "manufacturer_model_number", "price", "currency", "price_unit", "availability", "key_attributes", "image_link", "product_link" ], "properties": { "brand": { "type": [ "string", "null" ], "description": "Brand." }, "price": { "type": [ "number", "null" ], "description": "Public web list price in USD; null when Grainger shows none (discontinued, sign-in pricing)." }, "currency": { "type": "string", "description": "Currency code, always USD." }, "image_link": { "type": [ "string", "null" ], "description": "Product image link." }, "price_unit": { "type": [ "string", "null" ], "description": "What the price buys, such as each or pack of 6." }, "availability": { "type": [ "string", "null" ], "description": "Availability, such as Available or Product is Discontinued." }, "product_link": { "type": "string", "description": "Grainger product page link." }, "product_name": { "type": [ "string", "null" ], "description": "Product name as Grainger lists it." }, "key_attributes": { "type": "array", "items": { "type": "object", "required": [ "name", "value" ], "properties": { "name": { "type": "string", "description": "Specification name." }, "value": { "type": "string", "description": "Specification value." } }, "additionalProperties": false }, "description": "Up to 12 key specifications." }, "grainger_item_number": { "type": "string", "description": "Grainger item number." }, "manufacturer_model_number": { "type": [ "string", "null" ], "description": "Manufacturer model number." } }, "additionalProperties": false }, "description": "Products in the order Grainger shows them." } }, "additionalProperties": false}- Price
- 1 credit per completed run (1¢ with pay as you go); failed runs are free.
- Method
grainger.com/search_products- Returns
- product name, brand, Grainger item number, manufacturer model number, list price, currency, price unit, availability, key attributes, image, link
Use it from your agent
Give your agent this line. It reads SKILL.md, gets a Fous API key and connects the Fous MCP server. Its run then takes the method grainger.com/search_products with the inputs above.
Ask your agent
- Find nitrile disposable gloves on Grainger and show me list prices and brands
- Look up Grainger item number 5XN47 — what's the price and is it in stock?
- I need a 10 top options for cordless impact drivers with manufacturer model numbers and prices
- What do LED high bay lights cost? Give me product names, list prices, and key specs
- Pull up pricing for wet/dry shop vacuums from grainger.com, just the first 12 results
See more
Searches Best Buy US products with an optional price range, sort order and page. Prices and availability come from public listings and may vary by location.
bestbuy.com/search_productsSearches IKEA products in a chosen country and returns current prices, details, photos and reviews in IKEA's result order.
ikea.com/search_productsSearches Walmart products by keywords with optional sort and price range, returning prices, ratings, sellers and availability in Walmart's order. Uses Walmart's default location (no ZIP-based pricing).
walmart.com/search_productsSearches Trader Joe's public product catalogue by name or keywords, optionally within a main category. Prices are website reference prices and may vary by store.
traderjoes.com/search_productsSearches AliExpress listings by product words, shipping destination, price range and sort order. Unpriced promotional cards are omitted; free shipping is marked only when the listing explicitly says so.
aliexpress.com/search_productsSearches a named Instacart store's guest-visible grocery products for a US ZIP code. Prices are in USD and can differ from in-store prices; stock estimates can change.
instacart.com/search_productsFinds a Lowe's product by name, item number or product link and returns its details, price, specifications, images and availability at the nearest store for a ZIP code (or the site's default store).
lowes.com/get_productSearches Amazon products in a chosen country store, with price range, sort, Prime and page options. Returns the listings and prices shown to an anonymous shopper in the store's currency.
amazon.com/search_products