Looking for the overview — what this API returns, what it costs, and a call you can run without a key? See the KEH API page →
E-commerce & Marketplaces

KEH API & Scraper

The KEH API returns keh.com, the United States' largest managed used photo and video gear store, as clean JSON in five actions: search, product, facets, categories and suggest.

5 actionsLive JSON1,000 free credits$0.67–$1.50 / 1,000 creditsMCP-ready
Get a free keyOpen in playground

🤖 Using an AI assistant? Copy this link into ChatGPT / Claude / Cursor — it reads every endpoint and parameter instantly and tells you if this API fits your use case.

KEH is not a classifieds board. It buys gear in, inspects and grades it in its own facility and resells it with a warranty, so a listing is one model held in KEH's own cosmetic grades — New, Like New, Like New Minus, Excellent Plus, Excellent, Bargain, Ugly and As Is — and the grade is the product. The catalogue is 54,499 products deep, of which 7,553 are in stock today, and the API defaults to the in-stock ones on purpose: on a sold-out record KEH's index keeps a stale price and drops the grade entirely, so every row carries price_is_live_offer and units_in_stock and you can ask for the sold-out records deliberately with in_stock=any when you want them as price history. What makes this source unusually good to query is the depth of its own taxonomy, and all of it is a filter here: brand (577 values), KEH's grade (8), category (135 nodes), system (139 — Leica M, Nikon Manual Focus, Canon EOS, Large Format), gear type (91), coverage or film format (75), lens mount (257, from Canon EF down to Agfa Agfaflex), megapixels, film type, filter thread and filter type, prime versus zoom, focus type including the camera-motor versus lens-motor split that decides whether an old autofocus lens will focus on a modern body, maximum aperture (258 values including cine T-stops), focal-length range, memory-card type, special optical design (fisheye, macro, tilt-shift, mirror, pinhole), TTL flash system, intended use, KEH's own merchandising shelves (Overstock, New Lower Price, Newly Arrived, While Supplies Last) and price. Every one of those 25 filters was re-queried against the count KEH's own facet block claimed for it and 25 of 25 matched exactly, so a filter that bites and a filter that is ignored are never confused. The facets action returns that whole taxonomy live with KEH's counts, which is how you find the exact value instead of guessing it; categories walks the 135-node tree with ids, parents, breadcrumbs and counts; product opens one item with its full spec sheet, which grades KEH currently holds of it, its category breadcrumb, its unit count and its description; and suggest is KEH's own autocomplete, which matters here because KEH's search never answers empty and will relax a keyword that matches nothing into a catalogue slice instead. One honest limit, stated up front rather than discovered later: KEH's catalogue index carries ONE price per product, and measured against KEH's own product pages that price is the CHEAPEST grade's — a body indexed at 1,352.00 is offered at 1,352, 1,469 and 1,527 across its three grades — so the API publishes it as both price and price_from, publishes grades_available so you can see the rungs of the ladder, and sets per_grade_prices_available to false rather than pretending. No KEH account and no API key on their side: one ReefAPI key and the standard { ok, data, meta, error } envelope.

Reference

KEH's eight condition grades, and how much stock each one had on 2026-10-08

The grade names are KEH's own, carried verbatim; the value is what you pass to the grade filter, and the rank is a normalised best-to-worst number you can sort and threshold on. A grade exists only on gear KEH actually has in stock — on a sold-out record KEH drops it — so these counts are the in-stock catalogue. A product can hold several grades at once, which is why the grades add up past the 7,553 in-stock products.

grade (KEH's own name)grade valuerankproducts in stock
Newnew0567
Like Newlike_new1194
Like New Minuslike_new_minus21,740
Excellent Plusexcellent_plus32,199
Excellentexcellent44,218
Bargainbargain51,892
Uglyugly6505
As Isas_is718

KEH's short forms are accepted too: LN, LN-, EX+, EX, BGN, UG, As-Is. Several grades can be OR-ed in one call. The product action returns grades_available for one model, ranked best to worst, so you can see which rungs of the ladder KEH is holding right now.

Live example

Real request and response JSON

Captured from the indexed primary action, search, on .

Captured request
{
  "method": "POST",
  "url": "https://api.reefapi.com/keh/v1/search",
  "headers": {
    "x-api-key": "$REEF_KEY",
    "content-type": "application/json"
  },
  "body": {
    "query": "canon eos r6",
    "sort": "price_asc"
  }
}
Captured response
{
  "ok": true,
  "meta": {
    "api": "keh",
    "endpoint": "search",
    "mode": "live",
    "latency_ms": 637.3,
    "record_count": 24,
    "bytes": 141247,
    "cache_hit": false,
    "completeness_pct": 32,
    "currency": "USD",
    "page": 1,
    "page_size": 24,
    "sort": "price_asc",
    "pagination": {
      "page": 1,
      "page_size": 24,
      "has_more": true,
      "total_results": 75,
      "depth_limit": 10200,
      "reachable_results": 75,
      "depth_limit_reached": false
    },
    "filters_applied": {
      "in_stock": "true"
    },
    "search_page_url": "https://www.keh.com/shop/search?q=canon+eos+r6",
    "notes": "`price` is the cheapest grade's price — KEH's catalogue index carries no per-grade price; call `product` for the grades it holds. A keyword that matches nothing is relaxed by KEH's search instead of answering empty, so judge a long-tail query by the row titles.",
    "upstream_requests": 1,
    "total_results": 75,
    "charged_credits": 2,
    "version": "1.0.0",
    "request_id": "3e5ad0c3912f428e",
    "queue_ms": 1.1,
    "fetched_at": "2026-10-08T11:33:18.654Z"
  },
  "data": {
    "products": [
      {
        "pid": "390229",
        "title": "Canon ER-EOSR6 MarkII Neck Strap, Black/Red Edge with EOS R6 Mark II Stitched in Silver, 1.25 in.",
        "title_tokens": "[redacted-secret]",
        "brand": "Canon",
        "url": "https://www.keh.com/shop/28263457.html",
        "image": "https://cgi.keh.com/media/catalog/product/3/9/390229-4352156_01_r370x.jpg",
        "price": 2,
        "price_from": 2,
        "currency": "USD",
        "units_in_stock": 36,
        "in_stock": true,
        "price_is_live_offer": true,
        "description": null,
        "relevance_score": 507.5373
      },
      {
        "pid": "383969",
        "title": "Canon EOS R Instructions",
        "title_tokens": "[redacted-secret]",
        "brand": "Canon",
        "url": "https://www.keh.com/shop/canon-eos-r-instructions.html",
        "image": "https://cgi.keh.com/media/catalog/product/3/8/383969-3362366_01_r370x.jpg",
        "price": 2,
        "price_from": 2,
        "currency": "USD",
        "units_in_stock": 23,
        "in_stock": true,
        "price_is_live_offer": true,
        "description": null,
        "relevance_score": 504.4806
      },
      {
        "pid": "396176",
        "title": "Canon ER-EOSR6 MarkIII Neck Strap, Black/Red with EOS R6 Mark III Stitched in Silver, 1.25 in.",
        "title_tokens": "[redacted-secret]",
        "brand": "Canon",
        "url": "https://www.keh.com/shop/canon-er-eosr6-markiii-neck-strap-black-red-with-eos-r6-mark-iii-stitched-in-silver-1-25-in.html",
        "image": "https://cgi.keh.com/media/catalog/product/3/9/396176-6239549_01_r370x.jpg",
        "price": 19,
        "price_from": 19,
        "currency": "USD",
        "units_in_stock": 12,
        "in_stock": true,
        "price_is_live_offer": true,
        "description": null,
        "relevance_score": 506.7355
      }
    ]
  }
}
Actions

What the KEH API does

ActionDescriptionConcrete use caseKey params
searchSearch or browse KEH's catalogue. Pass `query`, or any combination of the twenty-six filters, or nothing at all to walk the whole shop. Every row carries KEH's own product id, title (with the brace shorthand KEH prints in it pulled out as `title_tokens`), brand, price, how many units are in stock, the product URL, image and description. `meta.total_results` is KEH's own exact match count for the request, so a filter that bites and a filter that is ignored are told apart without guessing, and `meta.search_page_url` is the public KEH page that shows the same slice. IN-STOCK ONLY BY DEFAULT: 46,946 of the 54,499 indexed products are sold out and their indexed price is stale, so pass `in_stock=any` if you want those records too. NOTE `price` is the CHEAPEST grade's price — the catalogue index carries no per-grade price (measured against the product page: one body indexed at $1,352 is offered at $1,352 / $1,469 / $1,527 across its three grades) — so call `product` to see which grades exist.Pricing teams call search to search or browse KEH's catalogue.query, brand, category, grade, system, ...
productThe complete record of ONE product by its `pid` (or by its keh.com `url`). Adds everything a search row cannot carry: WHICH of KEH's grades it currently holds of this model, ranked best to worst; its full spec sheet as KEH's own catalogue describes it (system, gear type, coverage format, lens mount, megapixels, film type, filter thread and type, prime/zoom, focus type, maximum aperture, focal length range, memory-card types, special optical design, TTL flash system, intended uses); its category breadcrumb; KEH's merchandising tags; the unit count; and the cleaned description. Honest about its one real gap: KEH's per-grade prices live only on the product page, which answers a challenge to everything, so `per_grade_prices_available` is false and the index's own `price_range` is republished as `price_range_index` beside `price_range_is_grade_blind: true` rather than passed off as a grade ladder. A pid KEH does not index answers NOT_FOUND.Marketplace operators call product to get the complete record of ONE product by its `pid` (or by its keh.com `url`).pid, url, include_pii
facetsThe live filter taxonomy of KEH's catalogue: every brand, grade, category, system, gear type, lens mount, format, aperture, filter size and type, card type, flash system and intended use that actually has stock right now, each with KEH's own count — plus the price and focal-length ranges as real numeric spans. This is how you discover the exact value to pass to `search` instead of guessing it, and the counts alone answer questions a listing cannot ('how many Canon EF lenses does KEH hold today', 'how much of the shop is Bargain grade'). Takes every filter `search` takes, so you can ask for the taxonomy INSIDE a scope — the lens mounts available under Fujifilm, say.Catalog enrichment teams call facets to get the live filter taxonomy of KEH's catalogue.facets, query, brand, category, grade, ...
categoriesKEH's own category tree — 135 nodes with their id, name, parent, readable breadcrumb and live product count, deepest counts first. Pass it any `search` filter to get the tree WITHIN a scope (which categories hold Leica gear, which hold something in Bargain grade). The ids it returns are exactly what the `category` filter takes.Retail analysts call categories to get kEH's own category tree.query, brand, category, grade, system, ...
suggestKEH's own search autocomplete: turn a half-typed camera or lens name into the queries KEH actually resolves. One small request (under 5 KB measured), meant to be called before `search` so a keyword lands on real gear — which matters here, because KEH's search never answers empty and will relax a miss into a catalogue slice instead.Pricing teams call suggest to get kEH's own search autocomplete.query, count, include_pii
Code samples

Call search from your stack

curl -X POST https://api.reefapi.com/keh/v1/search \
  -H "x-api-key: $REEF_KEY" \
  -H "content-type: application/json" \
  -d '{"query":"canon eos r6","sort":"price_asc"}'
MCP one-liner
Ask your MCP-connected assistant: call reefapi.keh.search with {"query":"canon eos r6","sort":"price_asc"}.
Use cases

Who uses this API and why

  • Price the US used-camera market by condition: pull every in-stock body of one brand with KEH's grade mix and price from, and see what Bargain costs against Excellent Plus on the same gear.
  • Build a lens finder that actually filters the way photographers think: mount, prime or zoom, focal-length range, maximum aperture, filter thread and whether the autofocus needs a motor in the lens or in the body.
  • Track supply and condition mix in used photo gear with KEH's own counts: 7,553 in stock of 54,499 indexed, 4,218 Excellent, 1,892 Bargain, 505 Ugly on 2026-10-08.
  • Source film gear by format and film type: 4,948 used film cameras, 2,915 large-format items, 2,633 that take 35mm roll, 278 that take 120 — filterable, with prices.
  • Watch KEH's own markdown shelves as a feed: Overstock 1,538, New Lower Price 735, Newly Arrived 392, While Supplies Last 4,728, each a single filter with a live count.
  • Benchmark your trade-in or resale pricing against a graded reference market where the grade vocabulary is published and every comparable carries a unit count.
FAQ

Questions developers ask before integrating

Is the price the one on the page?

It is KEH's own catalogue price, and we measured exactly what it means rather than assuming. KEH's catalogue index carries ONE price per product while a product page offers several condition grades at several prices, and checked against KEH's own pages the index price is the CHEAPEST grade's: the Canon EOS R6 body indexed at 1,352.00 is offered at 1,352 Excellent, 1,469 Excellent Plus and 1,527 Like New Minus. So the API publishes that figure twice — price, which is what KEH's listing shows, and price_from, which says what it means — and publishes grades_available so you can see which grades exist. The per-grade prices are not on this surface and per_grade_prices_available says so. The index also publishes a price_range field, and that field is a fake: it was [price, price] on all 1,600 rows we sampled, so it is returned only as price_range_index beside price_range_is_grade_blind rather than passed off as a grade ladder. All prices are plain US dollars; 1352.0 is 1,352.00 dollars, not cents.

Why does it only return in-stock gear by default?

Because 46,946 of KEH's 54,499 indexed products are sold out, and on a sold-out record the price left in the index is stale and the grade is gone. One measured example: a Leica M6 indexed at 1,266.00 with no grade, while KEH's own page still showed a Bargain copy at 3,200.00. Returning those by default would make 86 percent of every result set unbuyable and some of it wrong. So in_stock defaults to true, every row carries units_in_stock and price_is_live_offer, and you can pass in_stock=any or in_stock=false to get the sold-out records deliberately — they are genuinely useful as a what-KEH-handles list and as price history, as long as you know which they are.

How many units does KEH have, really?

The API returns units_in_stock, KEH's own unit count, and we checked that it is a real number rather than a figure that saturates at a round cap. Over 800 rows: with the in-stock filter the minimum is 1 and 0 never appears once, without it 0 is the single most common value, and there are 83 distinct counts with a maximum of 264 and no clustering at any ceiling. 0 and 'in stock' never occur together. The product page that would corroborate the number is behind KEH's own bot protection, so this is KEH's figure as KEH publishes it, and that is said rather than glossed over.

How do I know a filter actually did something?

Every response carries meta.total_results, KEH's own match count for your exact request, plus meta.filters_applied. More than that: all 25 filters were verified by asking KEH's facet block what a value should count and then re-querying that value as a filter — 25 of 25 matched exactly, including the long tail, where a lens mount with exactly one product returned exactly one. Against the 7,553 in-stock products in one run: Canon 783, Canon plus Nikon 1,688 (the exact sum, because values on one field are OR-ed), Bargain grade 1,892, Full Frame 35mm 2,034, Canon EF mount 437, prime lenses 1,897, autofocus with a lens motor 1,457, telephoto 593, f/2.8 589, camera bodies 656, Overstock 1,538, over 2,000 dollars 299, under 50 dollars 2,762, reaching past 400 mm 68. Different fields are AND-ed: Canon plus Excellent grade is 562 against 2,983 and 4,218. Two things the source does silently and the API refuses to: an unknown filter value returns zero rows rather than an error, and an unknown sort is ignored and the unsorted order handed back — so the API validates both itself and tells you.

How do I find the right filter value instead of guessing?

Call facets. It returns KEH's own live taxonomy — 25 of them, every brand, grade, category, system, gear type, lens mount, format, aperture, filter size and type, card type, flash system, optical design and intended use that has stock right now, each with KEH's own count, plus the price and focal-length ranges as real numeric spans. Every value it returns is a value search accepts, and it takes the same filters as search, so you can ask for the taxonomy inside a scope: the lens mounts available under Fujifilm came back as 9 values with counts. It also marks five values filterable: false — those are values KEH's own taxonomy advertises but cannot filter on, because their labels carry a stray trailing space in KEH's data and match zero products whichever way they are spelled. The API refuses those with that explanation instead of handing you an empty success.

Can I browse by category rather than search?

Yes, and the categories action gives you the map first: 135 nodes with their id, name, parent, readable breadcrumb and live product count, deepest counts first — Used Camera Lenses 15,795, Accessories 18,390, Used SLR and DSLR Lenses 9,939, Used Cameras 9,248, Used Film Cameras 4,948, Tripods and Supports 4,692. The ids it returns are exactly what the category filter takes, and a parent id includes its children. Pass it any search filter and you get the tree within that scope, which answers questions a flat listing cannot: which categories hold Leica gear came back as 58 of the 135.

Does it cover film gear, or only digital?

Film is a first-class part of this catalogue and of this API. KEH holds 4,948 used film cameras and 2,915 large-format items, and film-specific attributes are their own filters: film_type covers 35mm roll (2,633), 120 roll (278), 220 roll, 4x5 through 11x14 sheet, Instax, APS, 110 and 126 cartridges, 8mm, 16mm and Super 8. Coverage format runs from Full Frame 35mm down to 8x10 inch and up through medium format. Flash system covers the film-era TTL protocols by name — Canon A-TTL, Minolta TTL, Hasselblad TTL pre-flash and 18 more — which is exactly what you need to match an old flash to an old body.

What does the product action add over a search row?

Which of KEH's grades it currently holds of that model, ranked best to worst; the full spec sheet as KEH's own catalogue describes it — system, gear type, coverage format, lens mount, megapixels, film type, filter thread and type, prime or zoom, focus type, maximum aperture, focal-length range, memory-card types, special optical design, TTL flash system and intended uses; the category breadcrumb; KEH's merchandising tags; the unit count; and the cleaned description. You can call it with KEH's product id or by pasting a keh.com product URL. A product id KEH does not index answers NOT_FOUND, not an empty success.

Is there a seller to read?

No, and that is the nature of this source rather than something removed. KEH buys the gear, inspects and grades it and sells it itself, so there is no third-party merchant, seller profile or seller rating anywhere on the page — the warranty and the grade are KEH's own. Nothing is masked here; there is simply no seller entity to publish.

How deep does paging go?

To 10,200 rows per query, and the API tells you rather than letting you find out. That is KEH's search service's own hard cap — at most 200 rows per call and a start offset of at most 10,000, which it states in its own refusal — so meta.pagination carries depth_limit, reachable_results and depth_limit_reached, and asking past the cap is refused as an invalid parameter before a request is spent, with the advice to split the query by category, brand or price band. Paging itself is honest: pages one, two and three at 50 rows had zero overlapping products in either direction, so there is no silent repeat of the last page.

What happens with a keyword that matches nothing?

You get rows, and you should know that before you trust a long-tail query. KEH's search relaxes instead of answering empty: zzqqxxnotathingqq returned 1,217 products, qwertyasdfzxcv 870, a three-word nonsense phrase 4. The relevance score does not separate that fallback from a real hit (520.9 against 505.3) and KEH's own precision metadata reports the identical value in both cases, so there is no honest flag for us to compute and we do not invent one — it is stated on the query parameter and repeated in meta.notes, and the fix is to call suggest first so a keyword lands on gear KEH actually carries. A precise model name is exact: canon eos r6 returned 157, canon eos r6 mark ii black body 13, hasselblad 503cw 293.

What is the KEH API?

KEH API is a ReefAPI endpoint group for used cameras, lenses and film gear from keh.com as json: 54,000 products, 7,500 in stock, with keh's own condition grades, 25 measured filters and the live us price. It returns live JSON through POST requests under /keh/v1.

Is the KEH API free to try?

Yes. ReefAPI starts with 1,000 free credits, no card required. KEH calls use the same shared credit balance as every other ReefAPI engine.

Do I need a KEH login or account?

No login to KEH is needed for the API response. You call ReefAPI with your x-api-key header, and the playground can run live examples before you create a production key.

docs / keh

KEH

Used cameras, lenses and film gear from keh.com as JSON: 54,000 products, 7,500 in stock, with KEH's own condition grades, 25 measured filters and the live US price.

base /keh/v15 endpoints
post/keh/v1/product2 credits

The complete record of ONE product by its `pid` (or by its keh.com `url`). Adds everything a search row cannot carry: WHICH of KEH's grades it currently holds of this model, ranked best to worst; its full spec sheet as KEH's own catalogue describes it (system, gear type, coverage format, lens mount, megapixels, film type, filter thread and type, prime/zoom, focus type, maximum aperture, focal length range, memory-card types, special optical design, TTL flash system, intended uses); its category breadcrumb; KEH's merchandising tags; the unit count; and the cleaned description. Honest about its one real gap: KEH's per-grade prices live only on the product page, which answers a challenge to everything, so `per_grade_prices_available` is false and the index's own `price_range` is republished as `price_range_index` beside `price_range_is_grade_blind: true` rather than passed off as a grade ladder. A pid KEH does not index answers NOT_FOUND.

ParameterAllowed / rangeDescription
pidoptional—KEH's own product id, returned as `pid` by `search`. Pass this OR `url`. A pid that is not in the index answers NOT_FOUND, never an empty success.
urloptional—A keh.com product URL instead of a `pid` — paste the link straight from the shop. The index cannot be filtered by URL, so the engine resolves it through KEH's own keyword search over the slug and costs one extra upstream request; `pid` is the cheaper and exact way in.
include_pii = falseoptional—Standard gateway control. KEH is the seller of every item it lists, so no personal data appears on the surface this engine reads and this flag changes nothing in the response.
Try in playground →
post/keh/v1/facets1 credit

The live filter taxonomy of KEH's catalogue: every brand, grade, category, system, gear type, lens mount, format, aperture, filter size and type, card type, flash system and intended use that actually has stock right now, each with KEH's own count — plus the price and focal-length ranges as real numeric spans. This is how you discover the exact value to pass to `search` instead of guessing it, and the counts alone answer questions a listing cannot ('how many Canon EF lenses does KEH hold today', 'how much of the shop is Bargain grade'). Takes every filter `search` takes, so you can ask for the taxonomy INSIDE a scope — the lens mounts available under Fujifilm, say.

ParameterAllowed / rangeDescription
facetsoptionalbrand · category · film_type · filter_size · filter_type · flash_system · focal_length_max · focal_length_min · focus_type · format · gear_group · grade · in_stock · lens_design · lens_mount · lens_type · max_aperture · megapixels · memory_card · photography_type · price · product_type · system · tag · zoom_or_primeWhich filter taxonomies to return with their live counts. Left out, you get all 25 the index publishes. Every value here is a filter you can then pass to `search`, which is the point: discover the exact spelling instead of guessing it. `price`, `focal_length_min` and `focal_length_max` come back as a numeric `min`/`max` span rather than a value list, and `price` is the span the `price_min` / `price_max` filters work on.
queryoptional—Free-text keyword over KEH's catalogue (model, brand, lens, accessory). Leave it out to browse the whole catalogue and filter instead. ⚠️ MEASURED 2026-10-08: KEH's search RELAXES rather than answering empty, so a keyword that matches nothing still returns rows — 'zzqqxxnotathingqq' returned 1,217, 'qwertyasdfzxcv' 870, 'xyzzy plugh frobnitz' 4, 'gibberishwordhere' 1. The relevance score does not separate a real hit from that fallback (520.9 vs 505.3), so judge a long-tail keyword by the row titles, not by the fact that rows came back. A precise model name is exact: 'canon eos r6' 157 rows, 'canon eos r6 mark ii black body' 13, 'hasselblad 503cw' 293.
brandoptional—One or more brands as KEH spells them. 577 are live; the largest on 2026-10-08 are Nikon 3,782, Miscellaneous 3,163, Canon 2,983, Leica 2,850, Sigma 1,848, Pentax 1,629, Sony 1,366, Fuji 1,311, Olympus 1,301, Vivitar 1,231, Minolta 1,174, Hasselblad 1,134. Several values are OR-ed (measured: Canon 2,983 + Nikon 3,782 = 6,765). Call `facets` for the live list with counts.
categoryoptional—One or more of KEH's own category IDS (not names — the index filters on the id). 135 are live: 8226 Used Camera Lenses (15,795), 8231 Accessories (18,390), 8258 Used Cameras (9,248), 8227 Used SLR & DSLR Lenses (9,939), 8373 Used Film Cameras (4,948), 8369 Used Digital Cameras (4,323), 8240 Tripods & Supports (4,692)… A parent id includes its children. The `categories` action returns the whole tree with ids, parents, breadcrumbs and counts.
gradeoptionalnew · like_new · like_new_minus · excellent_plus · excellent · bargain · ugly · as_isKEH's OWN cosmetic grade — the field that makes a used-gear listing. KEH inspects and grades every item itself: new, like_new, like_new_minus, excellent_plus, excellent, bargain, ugly, as_is (its short forms LN, LN-, EX+, EX, BGN, UG are accepted too). Several values are OR-ed. ⚠️ A grade only exists on a product KEH actually has in stock: with `in_stock=false` the grade facet comes back EMPTY (measured), so combining `grade` with out-of-stock stock returns nothing, honestly.
systemoptional—KEH's own system family, which is how photographers actually shop a used catalogue: Tripods 3,481, Filters 3,138, Large Format 2,915, Nikon Manual Focus 2,443, Canon EOS 1,787, Nikon Autofocus 1,582, Sony E System 1,527, Leica M 1,485, Nikon Digital 1,415, Canon Digital 1,409, Canon Manual Focus 1,307… 139 live values; `facets` has the list.
product_typeoptional—KEH's own gear class, a finer cut than `category`: 'Fixed Focal Length Lenses, Mfg' 5,646, 'Fixed Focal Length Lenses, Non-Mfg' 4,967, Filters 4,188, 'Point & Shoots' 3,529, Bodies 3,494, 'Zoom Lenses, Non-Mfg' 3,370, 'Tripod Accessories' 1,749, 'Lens Shades' 1,497, Flashes 1,317… 91 live values.
formatoptional—Sensor or film coverage, in KEH's own spelling: 'Full Frame 35mm (24x36mm)' 14,010, 'APS-C & DX' 1,993, '4x5"' 968, 'Four Thirds' 763, '6x6 (56x56mm) & 2-1/4x2-1/4"' 688, '645 (56x42mm)' 367, '8x10"' 146… 75 live values.
lens_mountoptional—The lens bayonet, as KEH names it — 257 live values, which is the point of a catalogue this old: 'Canon EF' 1,629, 'Sony E Mount' 964, 'Sony A & Minolta A' 898, 'Leica M' 882, 'Canon FD' 848, 'Nikon F Mount Ai' 818, 'M42 - Pentax Screw' 744, 'Micro Four Thirds' 742, 'Minolta MD' 663 … down to 'Agfa Agfaflex III,IV,V & Ambiflex I,II,III' with exactly 1. Pass the spelling `facets` gives you; it is long and exact.
megapixelsoptional—Sensor resolution as KEH buckets it, including the unit: '16 MP' 794, '12 MP' 632, '10 MP' 388, '14 MP' 343, '24 MP' 314, '20 MP' 313, '45 MP', '60MP'… 49 live values, only set on digital bodies (4,098 products carry one).
film_typeoptional35mm roll · 120 roll · 220 roll · 4x5 sheet · 5x7 sheet · 8x10 sheet · 11x14 sheet · Instax Wide · Instax Square · APS cartridge · 110 cartridge · 126 cartridge · 127 roll · 116 roll · 620 roll · 8mm roll · 16mm roll · Super 8 cartridge · Polaroid Spectra cartridge · Polaroid Type 80 cartridgeWhich film the camera takes, with its 2026-10-08 counts. Only film gear carries it (3,507 products). Two values KEH's own taxonomy lists are left out of this list on purpose - 'Instax Mini' (37) and '70mm roll' (9) carry a stray trailing space in KEH's data and match ZERO products whichever way they are spelled (measured), so they are refused with that reason instead of answered with an empty success.
filter_sizeoptional—Filter thread / series size with its unit: '52mm' 1,977, '55mm' 1,554, '77mm' 1,441, '58mm' 1,374, '72mm' 1,369, '67mm' 1,252, '62mm' 1,241, '49mm' 1,025, '82mm' 627, '40.5mm (.5 pitch)' 299… 80 live values.
filter_typeoptionalUV / Haze / Skylight · Black & White Contrast · Polarizing - Circular Polarizers · ND - Fixed Neutral Density · Clear & Protective · Polarizing - Linear Polarizers · Diffuser / Soft Focus · ND - Graduated Neutral Density · Enhancing / Warming · IR - Infrared · Close-Up · Special Effects & Other · Color Conversion · ND - Center Neutral Density · Color Compensating · Scientific / AstronomyWhat an optical filter does, with its 2026-10-08 counts. KEH holds 4,189 filters, which is a real part of why people shop used. Two of KEH's own values are left out - 'ND - Variable Neutral Density' (58) and 'Cross-Screen / Star' (23) carry a stray trailing space in KEH's data and match ZERO products whichever way they are spelled (measured).
zoom_or_primeoptionalprime · zoomPrime or zoom. The complete live vocabulary (two values) with its counts.
focus_typeoptionalmanual_only · autofocus_lens_motor · autofocus_camera_motor · fixed_focus · manual_optionHow the lens focuses — the complete live vocabulary with its counts. The camera-motor vs lens-motor split is the one that decides whether an old autofocus lens will actually focus on a modern body.
lens_typeoptionalTelephoto / Long · Wide-Angle · Standard / Normal · Short Tele / Portrait · All-In-One · UltrawideAngle-of-view class — the complete live vocabulary with its 2026-10-08 counts. Several values are OR-ed.
max_apertureoptional—Maximum aperture in KEH's own notation, zooms included: 'f/2.8' 3,178, 'f/3.5' 1,585, 'f/4' 1,068, 'f/5.6' 1,057, 'f/4.5' 1,035, 'f/2' 956, 'f/1.4' 772, 'f/3.5-4.5' 588, 'f/4-5.6' 577, 'f/1.8' 528, and cine 'T1.5'… 258 live values.
memory_cardoptional—Which card the body takes: SDHC 1,698, SD 1,644, SDXC 1,478, 'SDXC UHS-I' 876, 'SDHC UHS-I' 815, 'Compact Flash (Type I)' 370, 'SDXC UHS-II' 292, 'CFxpress Type B' 58, 'CFast 2.0' 33… 32 live values. Two flaws in KEH's own data here, both reported rather than hidden: one value is the literal string '2931' (4 products), and 'Sony Memory Stick PRO Duo' (194) carries a stray trailing space that makes it unfilterable — that one is refused with the reason instead of answered with an empty success.
lens_designoptionalMacro Feature · Macro · Fisheye · Pancake · Tilt / Shift / Perspective Control · Mirror / Catadioptric · Soft Focus · Pinhole · Defocus Control · StereoSpecial optical design — the complete live vocabulary with its counts. Several values are OR-ed.
flash_systemoptional—Which TTL flash protocol the gear speaks, which is exactly what an old flash needs matching: 'Canon E-TTL' 318, 'Canon E-TTL II' 271, 'Olympus/Panasonic TTL' 236, 'Nikon i-TTL' 190, 'Minolta/Sony TTL (Pre-Flash)' 184, 'Canon TTL (Film Cameras)' 181… 22 live values, all of them in `facets`.
photography_typeoptionalTravel Photography · Portraiture / People Photography · Street Photography · Landscape Photography · Sports Photography · Wedding Photography · Family Photography · Concert / Music Photography · Wildlife Photography · Vlogging Photography · Astrophotography · Underwater Photography · Aerial PhotographyKEH's own 'what is this for' tag — the complete live vocabulary with its 2026-10-08 counts. Multi-valued per product, several values are OR-ed.
tagoptionalWhile Supplies Last · Overstock · New Lower Price · Back In Stock · Best Sellers · Newly Arrived · Featured Products · Rentable · Back To SchoolKEH's own merchandising shelves — this is how you ask 'what did KEH just mark down' or 'what arrived this week' in one call. The list is live and moves with the shop's campaigns; `facets` always has the current one with counts.
gear_groupoptionalLenses · Other Accessories · Filters · Camera Bodies · Other Filters · Tripod Accessories · Flashes & Lights · Bags & Cases · Finders · Lens Converters · UV Filters · Grips · Backs · Extension Tubes · Polarizing Filters · Memory & Readers · Straps · Mics · FilmKEH's coarse shop-grid grouping — the quickest way to split the catalogue into bodies vs lenses vs accessories without learning the 135-node category tree. The complete live vocabulary with its 2026-10-08 counts.
in_stock = trueoptionaltrue · false · anyWhether to return gear KEH actually has. DEFAULTS TO TRUE, deliberately: 46,946 of the 54,499 indexed products are sold out, and on a sold-out record the price left in the index is STALE and the grade is gone (measured on pid 386988: indexed $1,266.00 with no grade while KEH's own page still showed a Bargain copy at $3,200.00). Pass 'any' or 'false' to see the sold-out records anyway — they are useful as a price history and a what-KEH-handles list — and read `price_is_live_offer` on every row, which is false exactly there.
price_minoptional0–Lowest price to return, in US dollars as a decimal (e.g. 249.99). KEH's live band on 2026-10-08 ran from $1.00 to $24,242.00. Measured: 'Price:[100 TO 200]' returned 3,542 of 54,499.
price_maxoptional0–Highest price to return, in US dollars. ⚠️ It filters on the CHEAPEST grade's price, because that is the only price the catalogue index carries — see `price`.
focal_length_minoptional0–Only lenses that reach at least this focal length (mm) at the wide end. KEH's live range is 1-1,200 mm at the short end and 3.2-1,300 mm at the long end, on the 15,868 products that publish a focal length at all.
focal_length_maxoptional0–Only lenses whose long end is at most this focal length (mm).
include_pii = falseoptional—Standard gateway control. KEH is the seller of every item it lists, so no personal data appears on the surface this engine reads and this flag changes nothing in the response.
Try in playground →
post/keh/v1/categories1 credit

KEH's own category tree — 135 nodes with their id, name, parent, readable breadcrumb and live product count, deepest counts first. Pass it any `search` filter to get the tree WITHIN a scope (which categories hold Leica gear, which hold something in Bargain grade). The ids it returns are exactly what the `category` filter takes.

ParameterAllowed / rangeDescription
queryoptional—Free-text keyword over KEH's catalogue (model, brand, lens, accessory). Leave it out to browse the whole catalogue and filter instead. ⚠️ MEASURED 2026-10-08: KEH's search RELAXES rather than answering empty, so a keyword that matches nothing still returns rows — 'zzqqxxnotathingqq' returned 1,217, 'qwertyasdfzxcv' 870, 'xyzzy plugh frobnitz' 4, 'gibberishwordhere' 1. The relevance score does not separate a real hit from that fallback (520.9 vs 505.3), so judge a long-tail keyword by the row titles, not by the fact that rows came back. A precise model name is exact: 'canon eos r6' 157 rows, 'canon eos r6 mark ii black body' 13, 'hasselblad 503cw' 293.
brandoptional—One or more brands as KEH spells them. 577 are live; the largest on 2026-10-08 are Nikon 3,782, Miscellaneous 3,163, Canon 2,983, Leica 2,850, Sigma 1,848, Pentax 1,629, Sony 1,366, Fuji 1,311, Olympus 1,301, Vivitar 1,231, Minolta 1,174, Hasselblad 1,134. Several values are OR-ed (measured: Canon 2,983 + Nikon 3,782 = 6,765). Call `facets` for the live list with counts.
categoryoptional—One or more of KEH's own category IDS (not names — the index filters on the id). 135 are live: 8226 Used Camera Lenses (15,795), 8231 Accessories (18,390), 8258 Used Cameras (9,248), 8227 Used SLR & DSLR Lenses (9,939), 8373 Used Film Cameras (4,948), 8369 Used Digital Cameras (4,323), 8240 Tripods & Supports (4,692)… A parent id includes its children. The `categories` action returns the whole tree with ids, parents, breadcrumbs and counts.
gradeoptionalnew · like_new · like_new_minus · excellent_plus · excellent · bargain · ugly · as_isKEH's OWN cosmetic grade — the field that makes a used-gear listing. KEH inspects and grades every item itself: new, like_new, like_new_minus, excellent_plus, excellent, bargain, ugly, as_is (its short forms LN, LN-, EX+, EX, BGN, UG are accepted too). Several values are OR-ed. ⚠️ A grade only exists on a product KEH actually has in stock: with `in_stock=false` the grade facet comes back EMPTY (measured), so combining `grade` with out-of-stock stock returns nothing, honestly.
systemoptional—KEH's own system family, which is how photographers actually shop a used catalogue: Tripods 3,481, Filters 3,138, Large Format 2,915, Nikon Manual Focus 2,443, Canon EOS 1,787, Nikon Autofocus 1,582, Sony E System 1,527, Leica M 1,485, Nikon Digital 1,415, Canon Digital 1,409, Canon Manual Focus 1,307… 139 live values; `facets` has the list.
product_typeoptional—KEH's own gear class, a finer cut than `category`: 'Fixed Focal Length Lenses, Mfg' 5,646, 'Fixed Focal Length Lenses, Non-Mfg' 4,967, Filters 4,188, 'Point & Shoots' 3,529, Bodies 3,494, 'Zoom Lenses, Non-Mfg' 3,370, 'Tripod Accessories' 1,749, 'Lens Shades' 1,497, Flashes 1,317… 91 live values.
formatoptional—Sensor or film coverage, in KEH's own spelling: 'Full Frame 35mm (24x36mm)' 14,010, 'APS-C & DX' 1,993, '4x5"' 968, 'Four Thirds' 763, '6x6 (56x56mm) & 2-1/4x2-1/4"' 688, '645 (56x42mm)' 367, '8x10"' 146… 75 live values.
lens_mountoptional—The lens bayonet, as KEH names it — 257 live values, which is the point of a catalogue this old: 'Canon EF' 1,629, 'Sony E Mount' 964, 'Sony A & Minolta A' 898, 'Leica M' 882, 'Canon FD' 848, 'Nikon F Mount Ai' 818, 'M42 - Pentax Screw' 744, 'Micro Four Thirds' 742, 'Minolta MD' 663 … down to 'Agfa Agfaflex III,IV,V & Ambiflex I,II,III' with exactly 1. Pass the spelling `facets` gives you; it is long and exact.
megapixelsoptional—Sensor resolution as KEH buckets it, including the unit: '16 MP' 794, '12 MP' 632, '10 MP' 388, '14 MP' 343, '24 MP' 314, '20 MP' 313, '45 MP', '60MP'… 49 live values, only set on digital bodies (4,098 products carry one).
film_typeoptional35mm roll · 120 roll · 220 roll · 4x5 sheet · 5x7 sheet · 8x10 sheet · 11x14 sheet · Instax Wide · Instax Square · APS cartridge · 110 cartridge · 126 cartridge · 127 roll · 116 roll · 620 roll · 8mm roll · 16mm roll · Super 8 cartridge · Polaroid Spectra cartridge · Polaroid Type 80 cartridgeWhich film the camera takes, with its 2026-10-08 counts. Only film gear carries it (3,507 products). Two values KEH's own taxonomy lists are left out of this list on purpose - 'Instax Mini' (37) and '70mm roll' (9) carry a stray trailing space in KEH's data and match ZERO products whichever way they are spelled (measured), so they are refused with that reason instead of answered with an empty success.
filter_sizeoptional—Filter thread / series size with its unit: '52mm' 1,977, '55mm' 1,554, '77mm' 1,441, '58mm' 1,374, '72mm' 1,369, '67mm' 1,252, '62mm' 1,241, '49mm' 1,025, '82mm' 627, '40.5mm (.5 pitch)' 299… 80 live values.
filter_typeoptionalUV / Haze / Skylight · Black & White Contrast · Polarizing - Circular Polarizers · ND - Fixed Neutral Density · Clear & Protective · Polarizing - Linear Polarizers · Diffuser / Soft Focus · ND - Graduated Neutral Density · Enhancing / Warming · IR - Infrared · Close-Up · Special Effects & Other · Color Conversion · ND - Center Neutral Density · Color Compensating · Scientific / AstronomyWhat an optical filter does, with its 2026-10-08 counts. KEH holds 4,189 filters, which is a real part of why people shop used. Two of KEH's own values are left out - 'ND - Variable Neutral Density' (58) and 'Cross-Screen / Star' (23) carry a stray trailing space in KEH's data and match ZERO products whichever way they are spelled (measured).
zoom_or_primeoptionalprime · zoomPrime or zoom. The complete live vocabulary (two values) with its counts.
focus_typeoptionalmanual_only · autofocus_lens_motor · autofocus_camera_motor · fixed_focus · manual_optionHow the lens focuses — the complete live vocabulary with its counts. The camera-motor vs lens-motor split is the one that decides whether an old autofocus lens will actually focus on a modern body.
lens_typeoptionalTelephoto / Long · Wide-Angle · Standard / Normal · Short Tele / Portrait · All-In-One · UltrawideAngle-of-view class — the complete live vocabulary with its 2026-10-08 counts. Several values are OR-ed.
max_apertureoptional—Maximum aperture in KEH's own notation, zooms included: 'f/2.8' 3,178, 'f/3.5' 1,585, 'f/4' 1,068, 'f/5.6' 1,057, 'f/4.5' 1,035, 'f/2' 956, 'f/1.4' 772, 'f/3.5-4.5' 588, 'f/4-5.6' 577, 'f/1.8' 528, and cine 'T1.5'… 258 live values.
memory_cardoptional—Which card the body takes: SDHC 1,698, SD 1,644, SDXC 1,478, 'SDXC UHS-I' 876, 'SDHC UHS-I' 815, 'Compact Flash (Type I)' 370, 'SDXC UHS-II' 292, 'CFxpress Type B' 58, 'CFast 2.0' 33… 32 live values. Two flaws in KEH's own data here, both reported rather than hidden: one value is the literal string '2931' (4 products), and 'Sony Memory Stick PRO Duo' (194) carries a stray trailing space that makes it unfilterable — that one is refused with the reason instead of answered with an empty success.
lens_designoptionalMacro Feature · Macro · Fisheye · Pancake · Tilt / Shift / Perspective Control · Mirror / Catadioptric · Soft Focus · Pinhole · Defocus Control · StereoSpecial optical design — the complete live vocabulary with its counts. Several values are OR-ed.
flash_systemoptional—Which TTL flash protocol the gear speaks, which is exactly what an old flash needs matching: 'Canon E-TTL' 318, 'Canon E-TTL II' 271, 'Olympus/Panasonic TTL' 236, 'Nikon i-TTL' 190, 'Minolta/Sony TTL (Pre-Flash)' 184, 'Canon TTL (Film Cameras)' 181… 22 live values, all of them in `facets`.
photography_typeoptionalTravel Photography · Portraiture / People Photography · Street Photography · Landscape Photography · Sports Photography · Wedding Photography · Family Photography · Concert / Music Photography · Wildlife Photography · Vlogging Photography · Astrophotography · Underwater Photography · Aerial PhotographyKEH's own 'what is this for' tag — the complete live vocabulary with its 2026-10-08 counts. Multi-valued per product, several values are OR-ed.
tagoptionalWhile Supplies Last · Overstock · New Lower Price · Back In Stock · Best Sellers · Newly Arrived · Featured Products · Rentable · Back To SchoolKEH's own merchandising shelves — this is how you ask 'what did KEH just mark down' or 'what arrived this week' in one call. The list is live and moves with the shop's campaigns; `facets` always has the current one with counts.
gear_groupoptionalLenses · Other Accessories · Filters · Camera Bodies · Other Filters · Tripod Accessories · Flashes & Lights · Bags & Cases · Finders · Lens Converters · UV Filters · Grips · Backs · Extension Tubes · Polarizing Filters · Memory & Readers · Straps · Mics · FilmKEH's coarse shop-grid grouping — the quickest way to split the catalogue into bodies vs lenses vs accessories without learning the 135-node category tree. The complete live vocabulary with its 2026-10-08 counts.
in_stock = trueoptionaltrue · false · anyWhether to return gear KEH actually has. DEFAULTS TO TRUE, deliberately: 46,946 of the 54,499 indexed products are sold out, and on a sold-out record the price left in the index is STALE and the grade is gone (measured on pid 386988: indexed $1,266.00 with no grade while KEH's own page still showed a Bargain copy at $3,200.00). Pass 'any' or 'false' to see the sold-out records anyway — they are useful as a price history and a what-KEH-handles list — and read `price_is_live_offer` on every row, which is false exactly there.
price_minoptional0–Lowest price to return, in US dollars as a decimal (e.g. 249.99). KEH's live band on 2026-10-08 ran from $1.00 to $24,242.00. Measured: 'Price:[100 TO 200]' returned 3,542 of 54,499.
price_maxoptional0–Highest price to return, in US dollars. ⚠️ It filters on the CHEAPEST grade's price, because that is the only price the catalogue index carries — see `price`.
focal_length_minoptional0–Only lenses that reach at least this focal length (mm) at the wide end. KEH's live range is 1-1,200 mm at the short end and 3.2-1,300 mm at the long end, on the 15,868 products that publish a focal length at all.
focal_length_maxoptional0–Only lenses whose long end is at most this focal length (mm).
include_pii = falseoptional—Standard gateway control. KEH is the seller of every item it lists, so no personal data appears on the surface this engine reads and this flag changes nothing in the response.
Try in playground →
post/keh/v1/suggest1 credit

KEH's own search autocomplete: turn a half-typed camera or lens name into the queries KEH actually resolves. One small request (under 5 KB measured), meant to be called before `search` so a keyword lands on real gear — which matters here, because KEH's search never answers empty and will relax a miss into a catalogue slice instead.

ParameterAllowed / rangeDescription
queryrequired—A partial model or brand name — KEH's own search box resolves it the same way. At least three characters (KEH's own widget waits for three).
count = 10optional1–20How many suggestions to return (1-20, default 10). KEH's service returns a fixed group and this trims it, so asking for more than it holds is not an error.
include_pii = falseoptional—Standard gateway control. KEH is the seller of every item it lists, so no personal data appears on the surface this engine reads and this flag changes nothing in the response.
Try in playground →
Built for volume
5M+ requests a day

Measured at 60 requests a second across the fleet, with no central bottleneck. Volume pricing is on request, and per-key limits are raised for high-volume accounts.

Missing a source?
We build it

Tell us a site we do not cover yet and it becomes an engine. A customer asked for bestprice.gr on a Sunday and it was in the catalog the next day.

Support
2 minute median reply

Median time from a question in the live chat to the first answer, measured across every answered conversation. Setup help included, no support tier to buy.

One key, one balance
Every API included

No per-site plans and no separate subscriptions. One key and one credit pool across the whole catalog, so adding a source costs nothing up front.

Planning something large? Tell us the volume and the sources and we will come back with what it costs and what we would have to build.