eBay Image Search API (Sold Prices From a Photo)
Send a photo and get eBay sold listings for that item. POST /v1/scrape/image identifies the product, shows the keyword it used, and runs the full sold search. 2 requests per success, nothing when the photo cannot be identified.
Price an item from a photo. POST /v1/scrape/image reads the photo, identifies the product (brand, model,
variant, and for trading cards the set, card number, grader and grade), turns it into an eBay search keyword,
and runs the normal sold search with it. The response shows exactly what we identified
and searched for, followed by up to 240 sold listings and the price summary.
- 2 requests per successful search: 1 to read the photo, 1 for the sold search.
- Nothing charged when the photo cannot be identified (
422 image_not_identified) or the search fails. - Every sold search option works:
ebaySite,count,itemCondition,bestOfferPrice,sellerCountry,postalCodeand the rest, passed in the query string. - You see the keyword. If the photo is read wrong, search again with
GET /v1/scrapeand your own keyword.
Make a request
Upload the photo as the multipart field image:
curl --fail-with-body \
-H "Authorization: Bearer cs_live_REPLACEWITHYOURKEY" \
-F "[email protected]" \
"https://api.compsniper.com/v1/scrape/image?count=60"Or pass a public image link:
curl --fail-with-body \
-H "Authorization: Bearer cs_live_REPLACEWITHYOURKEY" \
-H "Content-Type: application/json" \
-d '{"imageUrl": "https://example.com/photos/charizard-psa10.jpg"}' \
"https://api.compsniper.com/v1/scrape/image?count=60&bestOfferPrice=true"import requests
with open("sneaker.jpg", "rb") as photo:
response = requests.post(
"https://api.compsniper.com/v1/scrape/image",
headers={"Authorization": "Bearer cs_live_REPLACEWITHYOURKEY"},
params={"count": 60},
files={"image": ("sneaker.jpg", photo, "image/jpeg")},
timeout=120,
)
if response.status_code == 422:
print(response.json()["error"]) # not identified, not charged
else:
response.raise_for_status()
data = response.json()
print("Searched for:", data["identified"]["keyword"], data["identified"]["confidence"])
print("Median sold price:", data["summary"]["median"], "from", data["summary"]["count"], "sales")import { readFile } from "node:fs/promises";
const form = new FormData();
form.append("image", new Blob([await readFile("watch.jpg")], { type: "image/jpeg" }), "watch.jpg");
const res = await fetch("https://api.compsniper.com/v1/scrape/image?count=60", {
method: "POST",
headers: { Authorization: "Bearer cs_live_REPLACEWITHYOURKEY" },
body: form,
});
const data = await res.json();
console.log(data.identified?.keyword, data.summary?.median);Ways to send the photo
| How | Request |
|---|---|
| File upload | multipart/form-data with the field image |
| Raw image body | Content-Type: image/jpeg (or image/png, image/webp, image/gif, image/heic) with the bytes as the body |
| Public link | JSON body {"imageUrl": "https://..."}, or ?imageUrl= in the query string |
Images up to 8 MB. Links must be public https:// addresses.
Example response
The identified block comes first, then the same fields as GET /v1/scrape.
{
"identified": {
"keyword": "LEGO Star Wars Millennium Falcon 75192",
"confidence": 1,
"category": "toy",
"details": { "brand": "LEGO", "model": "Millennium Falcon", "set": "75192" }
},
"requestsCharged": 2,
"keyword": "LEGO Star Wars Millennium Falcon 75192",
"page": 1,
"hasNextPage": true,
"summary": { "count": 60, "currency": "USD", "median": 949.99, "mean": 921.43, "min": 700, "max": 1099, "p25": 908.15, "p75": 949.99 },
"items": [ "... sold listings, the same fields as /v1/scrape ..." ]
}| Field | Description |
|---|---|
identified.keyword | The eBay search we ran. |
identified.confidence | 0 to 1. Photos below 0.6 are refused rather than guessed. |
identified.category | trading_card, sneakers, electronics, clothing, toy, watch, collectible, media or other. |
identified.details | What was read from the photo: brand, model, variant, color, size, year, set, cardNumber, player, grader, grade (only the ones found). |
requestsCharged | 2 on success. |
Tips for photos that identify well
- Show the label, the box front, the model number or the card front. For graded cards, include the slab label.
- One item per photo, filling most of the frame.
- If the model or generation cannot be told from the outside (for example the storage size of a phone), the photo
is refused rather than guessed. Search with
GET /v1/scrapeand the exact model instead.
Errors
| Situation | Status | Charged |
|---|---|---|
| Photo identified and sold search returned | 200 | 2 requests |
| Photo does not show one identifiable item, or confidence below 0.6 | 422 image_not_identified | no |
| Image link unreachable or not an image | 422 image_unavailable / invalid_image | no |
| Image larger than 8 MB | 413 invalid_image | no |
| More than 20 photos in a minute | 429 rate_limited | no |
| Not enough requests left for both steps | 429 quota_exceeded | no |
| Sold search failed after identification | the search error, with identified included | no |
eBay Item Details API (Sold Listings Included)
Get the condition, seller notes, item specifics and full description of any eBay listing by item ID, sold listings included, with GET /v1/items/details. One request per lookup, never charged when eBay no longer has the listing.
Shipping Rates API
Get eBay shipping-rate estimates from US ZIP codes, package weight, and dimensions without purchasing a label.