Use case
Image similarity API for marketplace fraud detection
Marketplaces face a steady drip of copied product photos, recycled listings, and coordinated seller fraud. This article walks through using POST /image/match to surface those listings at scale — with code in cURL, Python, and Node.
What sellers actually do to evade detection
If you're guarding a marketplace, you've already seen these moves: download a competing seller's hero image, watermark it, recompress it, mirror it, swap the background, paste it on a new template. Each of those changes flips a content hash but not the perceived image.
An effective dedupe layer has to be invariant to those edits. That's what /image/match is built for: a perceptual similarity score, not an exact-match check.
The endpoint
Two URLs in, structured envelope out. matched_segments is empty for image responses; the score and confidence are what drive the decision.
{
"match": true,
"confidence": "high",
"similarity_score": 0.94,
"processing_time_ms": 38,
"media_type": "image",
"matched_segments": []
}cURL — quick test
curl -X POST https://medialayer-image-audio-video-matching-api.p.rapidapi.com/image/match \
-H "x-rapidapi-key: YOUR_RAPIDAPI_KEY" \
-H "x-rapidapi-host: medialayer-image-audio-video-matching-api.p.rapidapi.com" \
-H "Content-Type: application/json" \
-d '{
"source_url": "https://cdn.example.com/listing-12345.jpg",
"target_url": "https://cdn.example.com/catalog-ref-987.jpg"
}'Python — listing-creation gate
The simplest production pattern: when a seller submits a new listing, compare its hero image to a small reference catalog of known products and known-banned images. If the score crosses a threshold, route to manual review.
import requests
API_URL = "https://medialayer-image-audio-video-matching-api.p.rapidapi.com/image/match"
HEADERS = {
"x-rapidapi-key": "YOUR_RAPIDAPI_KEY",
"x-rapidapi-host": "medialayer-image-audio-video-matching-api.p.rapidapi.com",
"Content-Type": "application/json",
}
def gate_listing(listing_image_url: str, references: list[str]) -> str:
"""Return one of: 'auto-block', 'review', 'pass'."""
for ref_url in references:
r = requests.post(
API_URL,
json={"source_url": listing_image_url, "target_url": ref_url},
headers=HEADERS,
timeout=30,
)
r.raise_for_status()
data = r.json()
score = data["similarity_score"]
if score >= 0.97:
return "auto-block" # near-identical image
if score >= 0.85:
return "review" # near-duplicate, send to T&S queue
return "pass"Node.js — fan-out with a concurrency cap
Most marketplaces don't compare against a single reference image — they fan out to a curated set. Bound concurrency so a single listing doesn't burst against your RapidAPI plan's per-second limit.
const API_URL =
"https://medialayer-image-audio-video-matching-api.p.rapidapi.com/image/match";
const HEADERS = {
"x-rapidapi-key": "YOUR_RAPIDAPI_KEY",
"x-rapidapi-host": "medialayer-image-audio-video-matching-api.p.rapidapi.com",
"Content-Type": "application/json",
};
async function matchOne(source: string, target: string) {
const res = await fetch(API_URL, {
method: "POST",
headers: HEADERS,
body: JSON.stringify({ source_url: source, target_url: target }),
});
if (!res.ok) throw new Error(`MediaLayer ${res.status}`);
return res.json() as Promise<{ similarity_score: number }>;
}
async function topMatch(listing: string, references: string[]) {
// Bound to 4 concurrent calls. Tune to your plan.
const queue = [...references];
let best = 0;
await Promise.all(
Array.from({ length: 4 }).map(async () => {
while (queue.length) {
const ref = queue.shift()!;
const { similarity_score } = await matchOne(listing, ref);
if (similarity_score > best) best = similarity_score;
}
}),
);
return best;
}Pairwise won't scale forever
If your reference catalog is in the low thousands, the public API and a fan-out pattern works fine. Past that, pairwise calls per listing become wasteful and slow — you're doing N comparisons to find a top match.
That's where the Enterprise media search surface fits: ingest your reference media into a similarity index, run one-to-many lookups on every new listing, and get top-K matches with scores in a single call. Same matching primitives, different access pattern.
Trust & safety considerations
- Cluster, don't score in isolation — Group listings whose images match at a high threshold; resolve the cluster as one decision. Reviewers stop seeing 40 copies of the same flagged image.
- Keep the key server-side — x-rapidapi-key never belongs in a mobile or web bundle — proxy through your backend.
- Stay inside size caps — Image uploads are capped at 15 MB per request. Resize at upload time so the matching pipeline doesn't reject hero images.
- Treat URLs as untrusted — URL validation rejects private, loopback, and cloud-metadata addresses up front — useful when seller-supplied URLs occasionally point at internal staging buckets.
Endpoints used in this article
POST /image/match
Compare two images. Built to survive watermarking, cropping, re-encoding, and mirroring — the moves marketplace fraud actually uses.
See full reference →POST /video/match
When sellers reuse unboxing or demo videos, /video/match returns aligned segments showing where two clips overlap.
See full reference →Related articles
Near-duplicate media detection: image, video, and audio in one API
The broader concept: why near-duplicate detection is harder than exact-match hashing.
Read article →Creative audit API for ad-tech
Same matching primitives applied to ad creatives, campaign assets, and brand-safety review.
Read article →Keep exploring
Marketplaces solution
How the matching primitives plug into listing creation, T&S review, and brand-protection programs.
Open →Image playground
Run /image/match against two URLs in your browser, no key required.
Open →Enterprise media search
One-to-many search against millions of indexed listings — for catalogs that have outgrown pairwise calls.
Open →Ready to wire it in?
Subscribe on RapidAPI to call the public API on your own key, or talk to MediaLayer AI Labs about enterprise direct API access.