# Reverse Image Search Monitor: Discover, Verify & Track Matches (`getascraper/reverse-image-search-monitor`) Actor

Automatically discovers every site hosting your image via reverse image search, then verifies each candidate with CLIP similarity and perceptual hashing for duplicate and near-duplicate verdicts, not just one score. Monitor mode flags only new copies on repeat scans. From $0.0025 per candidate.

- **URL**: https://apify.com/getascraper/reverse-image-search-monitor.md
- **Developed by:** [GetAScraper](https://apify.com/getascraper) (community)
- **Categories:** AI, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.87 / 1,000 candidate records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Reverse Image Search Monitor: Discover, Verify & Track Matches

<table width="100%" style="width:100%;min-width:100%;border-collapse:collapse;table-layout:fixed;margin-bottom:20px">
<tbody style="display:table;width:100%;min-width:100%;border-collapse:collapse;table-layout:fixed">
<tr style="width:100%">
<td style="background:#0F172A;color:#FFFFFF;padding:28px 24px;text-align:center;border-radius:8px">
<div style="font-size:22px;font-weight:700;margin-bottom:8px">Find every copy of your image, verified twice</div>
<div style="font-size:15px;color:#CBD5E1">Search the open web from one image, confirm real matches with two independent checks, and get alerted the moment a new copy appears.</div>
</td>
</tr>
</tbody>
</table>

<table width="100%" style="width:100%;min-width:100%;border-collapse:collapse;table-layout:fixed;margin-bottom:20px">
<tbody style="display:table;width:100%;min-width:100%;border-collapse:collapse;table-layout:fixed">
<tr style="width:100%">
<td width="25%" style="width:25%;background:#EEF2FF;padding:16px;text-align:center;border-radius:8px">
<div style="font-size:14px;font-weight:700;color:#1E293B">🔍 Finds candidates for you</div>
<div style="font-size:13px;color:#475569;margin-top:6px">Start from one image. No need to already have a list of suspects.</div>
</td>
<td width="25%" style="width:25%;background:#EEF2FF;padding:16px;text-align:center;border-radius:8px">
<div style="font-size:14px;font-weight:700;color:#1E293B">🎯 Two signals, one verdict</div>
<div style="font-size:13px;color:#475569;margin-top:6px">Visual similarity and a structural fingerprint check both have to agree before we call it a duplicate.</div>
</td>
<td width="25%" style="width:25%;background:#EEF2FF;padding:16px;text-align:center;border-radius:8px">
<div style="font-size:14px;font-weight:700;color:#1E293B">📋 Bring your own targets too</div>
<div style="font-size:13px;color:#475569;margin-top:6px">Already have a candidate list? Score it directly with the same dual-signal rigor.</div>
</td>
<td width="25%" style="width:25%;background:#EEF2FF;padding:16px;text-align:center;border-radius:8px">
<div style="font-size:14px;font-weight:700;color:#1E293B">🛰️ Watches over time</div>
<div style="font-size:13px;color:#475569;margin-top:6px">Turn on monitor mode and hear about it only when a genuinely new site appears.</div>
</td>
</tr>
</tbody>
</table>

### 🔍 What does Reverse Image Search Monitor do?

Give it one image, a URL or an upload, and it searches the open web for every place that image (or a close visual match) shows up. Every candidate it finds gets verified two independent ways: a visual-similarity score and a structural fingerprint check, so a "duplicate" call is backed by two signals agreeing, not one noisy number. Turn on monitor mode and it remembers what it saw last time, so a later scheduled run only reports genuinely new hosting sites, not everything all over again.

Already have your own list of candidate images to check instead? Skip discovery and score that list directly, with the same two-signal verification.

Run it on demand from the [Apify Console](https://console.apify.com), on a schedule for ongoing monitoring, or through the [Apify API](https://docs.apify.com/api/v2) and integrations like Zapier or Make.

### 💡 Why use Reverse Image Search Monitor?

**Photographers and illustrators** can find out who's using their work without permission, not just check the handful of sites they already suspect.

**Brands and sellers** can catch counterfeit listings and copied product photos before they cost a sale.

**E-commerce and catalog teams** can dedupe a product catalog against the open web, not just against itself.

**Content and marketing teams** can confirm an image is actually original before publishing it under their own name.

### 🧭 How to use Reverse Image Search Monitor

<table width="100%" style="width:100%;min-width:100%;border-collapse:collapse;table-layout:fixed;margin:16px 0">
<tbody style="display:table;width:100%;min-width:100%;border-collapse:collapse;table-layout:fixed">
<tr style="width:100%">
<td width="33%" style="width:33.333%;background:#F8FAFC;padding:16px;text-align:center;border-radius:8px">
<div style="font-size:20px;font-weight:700;color:#0F172A">1</div>
<div style="font-size:14px;font-weight:700;color:#1E293B;margin-top:4px">Add your image</div>
<div style="font-size:13px;color:#475569;margin-top:6px">Paste an image URL or upload a file in the Input tab.</div>
</td>
<td width="33%" style="width:33.333%;background:#F8FAFC;padding:16px;text-align:center;border-radius:8px">
<div style="font-size:20px;font-weight:700;color:#0F172A">2</div>
<div style="font-size:14px;font-weight:700;color:#1E293B;margin-top:4px">Choose a mode</div>
<div style="font-size:13px;color:#475569;margin-top:6px">Let it discover candidates, score your own target list, or both.</div>
</td>
<td width="33%" style="width:33.333%;background:#F8FAFC;padding:16px;text-align:center;border-radius:8px">
<div style="font-size:20px;font-weight:700;color:#0F172A">3</div>
<div style="font-size:14px;font-weight:700;color:#1E293B;margin-top:4px">Run and review</div>
<div style="font-size:13px;color:#475569;margin-top:6px">Get a scored, ranked list of matches in the Output tab, or turn on monitoring for ongoing alerts.</div>
</td>
</tr>
</tbody>
</table>

1. Click **Try for free** and open the Input tab.
2. Paste a direct image URL or upload the image you want to check.
3. Pick a mode: automatic discovery, your own target list, or both.
4. Optionally turn on **Incremental Monitor Mode** and give it a name, then schedule the Actor to run periodically. Later runs will only report new appearances.
5. Click **Start** and review results in the Output tab, or export them as JSON, CSV, or Excel.

### ⚙️ Input

Configure the run from the Input tab in Apify Console, or pass JSON directly through the API.

| Field | Type | Required | Description |
|---|---|---|---|
| `sourceImage` | string | Yes | Direct image URL or an uploaded image to search for. |
| `mode` | enum | No | `discover` (default), `compareTargets`, or `both`. |
| `targetImages` | array of URLs | No | Explicit candidate image URLs to score, used with `compareTargets` or `both`. Up to 20. |
| `comparisonMode` | enum | No | `embedding`, `phash`, or `both` (default). Which verification signals to run. |
| `similarityThreshold` | number | No | Visual-similarity cutoff (0 to 1) for a duplicate verdict. Default 0.85. |
| `phashThreshold` | integer | No | Structural fingerprint distance cutoff (0 to 64) for a duplicate verdict. Default 8. |
| `proxyConfiguration` | object | No | Proxy settings. Defaults to Apify's standard proxy. |
| `maxCandidates` | integer | No | Maximum candidates to discover, download, and score per run. Default 12. |
| `incrementalMonitorMode` | boolean | No | When on, only reports candidates that are new or changed since the last run with this monitor state name. |
| `monitorStateName` | string | No | Name for the saved monitor state. Use a different name per image tracked on its own schedule. |
| `customId` | string | No | Your own identifier, echoed back on every output row. |

### 📊 Data table

| Field | Type | Description |
|---|---|---|
| `customId` | string | Your own identifier, if you set one. |
| `candidateUrl` | string | The matching image or hosting page URL. |
| `candidateSite` | string | The hosting site's domain, when available. |
| `discoveryMethod` | string | `reverseSearch` if found automatically, `explicitTarget` if you supplied it. |
| `similarityScore` | number | Visual-similarity score from 0 to 1, when embedding verification ran. |
| `phashDistance` | number | Structural fingerprint distance, when hash verification ran. |
| `dhashDistance` | number | A second, independent structural fingerprint distance. |
| `isDuplicate` | boolean | True when the verification signals confirm a match. |
| `isNearDuplicate` | boolean | True when one signal suggests a match but it falls short of a confirmed duplicate. |
| `verdict` | string | `duplicate`, `near_duplicate`, `related`, or `unverified`. |
| `changeType` | string | `NEW` or `UPDATED`, only present in monitor mode. |
| `scrapedAt` | string | When this row was produced. |

#### Example output

```json
{
  "candidateUrl": "https://example.com/gallery/photo-42.jpg",
  "candidateSite": "example.com",
  "discoveryMethod": "reverseSearch",
  "similarityScore": 0.94,
  "phashDistance": 3,
  "dhashDistance": 2,
  "isDuplicate": true,
  "isNearDuplicate": false,
  "verdict": "duplicate",
  "scrapedAt": "2026-09-11T09:00:00.000Z"
}
```

You can download results as JSON, CSV, Excel, or HTML from the Output tab, or pull them through the API.

### 💰 Pricing

This Actor is pay per event. You only pay for what it actually finds and scores, and an empty run costs nothing. There are no subscriptions or minimum monthly fees.

### ⭐ Enjoying Reverse Image Search Monitor?

<table width="100%" style="display:table;width:100%;min-width:100%;border-collapse:collapse;table-layout:fixed"><tr><td style="padding:20px 24px 14px;background:#EEF2FF;border:1px solid #C7D2FE;border-left:5px solid #0F172A;border-radius:10px 10px 0 0"><span style="font-size:20px;letter-spacing:4px">⭐ ⭐ ⭐ ⭐ ⭐</span><br><span style="font-size:17px;font-weight:800;color:#1E293B">If it caught a match you would have otherwise missed, that's worth a rating.</span><br><span style="font-size:14px;color:#475569">It helps other photographers, sellers, and content teams find it too.</span></td></tr><tr><td style="padding:0;background:#0F172A;border:1px solid #C7D2FE;border-top:none;border-radius:0 0 10px 10px;text-align:center"><a href="https://apify.com/getascraper/reverse-image-search-monitor/reviews" style="display:block;padding:13px 16px;color:#FFFFFF;text-decoration:none;font-weight:800;font-size:15px;letter-spacing:0.3px">★&nbsp;&nbsp;Rate this Actor on Apify</a></td></tr></table>

### ❓ FAQ

**Does it need my image to already be indexed anywhere?**
No. Give it any direct, publicly reachable image URL or upload a file, and it searches from there.

**What if I already know which images to compare against?**
Set mode to `compareTargets` and list them directly. You get the same two-signal verification without the discovery step.

**How does monitor mode decide what's "new"?**
It remembers what it found under a given monitor state name and only reports candidates that are genuinely new or changed the next time that same state name runs.

**Why do I sometimes see "near duplicate" instead of "duplicate"?**
That means one verification signal found a strong match but the other did not agree. It is still worth a look, just flagged with the right amount of confidence instead of an overconfident guess.

### 🔗 Other actors

- [Mercari Japan Scraper: メルカリ listings, prices and changes](https://apify.com/getascraper/mercari-japan-scraper) ↗ - Scrape live listings and sold comps from Mercari Japan.
- [Wildberries Product Scraper: Поиск товаров Вайлдберриз](https://apify.com/getascraper/wildberries-scraper) ↗ - Pull product, pricing, and seller data from Wildberries.
- [Google Maps List Scraper: Curated Places & Leads](https://apify.com/getascraper/google-maps-list-scraper) ↗ - Extract places from any Google Maps list or search.
- [Betano Odds Scraper: Full Match Odds & Price-Move Monitor](https://apify.com/getascraper/betano-odds-scraper) ↗ - Pull upcoming fixtures and market odds from Betano.
- [Indeed Flex Shift Monitor: Pay Rates & Shift Alerts](https://apify.com/getascraper/indeed-flex-shift-monitor) ↗ - Track shift listings and pay rates on Indeed Flex.

# Actor input Schema

## `sourceImage` (type: `string`):

The image you want to search for, as a direct http(s) image URL or a base64 data URI. A data URI is temporarily re-hosted by this Actor so the reverse-image-search step has a real URL to fetch, and is not kept after the run.

## `mode` (type: `string`):

Discover finds candidate images across the open web from just the source image, a capability no named competitor (image-comparator, image-similarity-api, image-diff) offers at all. Compare targets scores an explicit list you already have, matching image-similarity-api's own input shape. Both runs discovery and your target list together.

## `targetImages` (type: `array`):

Explicit candidate image URLs to score against the source image. Only used when Mode is "Compare against my target images" or "Both". Capped at 20 per run; split a larger list across multiple runs.

## `comparisonMode` (type: `string`):

Embedding uses a CLIP visual-similarity score (0 to 1). Perceptual hash uses pHash and dHash bit-distance, a second independent signal. Both runs the same dual-signal verification as image-similarity-api, stronger than image-comparator's single score and image-diff's plain pixel diff.

## `similarityThreshold` (type: `number`):

Minimum CLIP cosine similarity (0 to 1) for a candidate to count as a duplicate. Lower this to catch looser visual matches, raise it to only flag near-exact copies.

## `phashThreshold` (type: `integer`):

Maximum Hamming distance out of 64 bits between the source and candidate perceptual hashes for a duplicate verdict. Lower is stricter; 0 means the hashes must match exactly.

## `proxyConfiguration` (type: `object`):

Datacenter proxy is the default and is normally enough for the reverse-image-search step. Switch to a residential group only if runs start failing, since reliability at high query volume against the search engine has not been stress-tested.

## `maxCandidates` (type: `integer`):

Maximum number of candidate images to discover, download and score in one run. Each candidate costs one image fetch plus one local similarity computation, so this is the main driver of run time and cost. Kept low by default so a default run finishes in a few minutes.

## `incrementalMonitorMode` (type: `boolean`):

When on, this run compares its candidates against the last run that used the same Monitor State Name and only reports genuinely new hosting sites since then, real image-appearance monitoring the way paid reverse-image-search alert tools do. Off by default so a first run always reports the full picture.

## `monitorStateName` (type: `string`):

Name for the saved monitor state when Incremental Monitor Mode is on. Use a different name per source image you track on its own schedule, otherwise their histories mix together.

## `customId` (type: `string`):

Optional identifier echoed back on every output row, useful for joining results to your own database when running this Actor for many source images.

## Actor input object example

```json
{
  "sourceImage": "https://raw.githubusercontent.com/github/explore/main/topics/react/react.png",
  "mode": "discover",
  "targetImages": [],
  "comparisonMode": "both",
  "similarityThreshold": 0.85,
  "phashThreshold": 8,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "maxCandidates": 12,
  "incrementalMonitorMode": false,
  "monitorStateName": "default",
  "customId": ""
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "sourceImage": "https://raw.githubusercontent.com/github/explore/main/topics/react/react.png",
    "mode": "discover",
    "targetImages": [],
    "comparisonMode": "both",
    "similarityThreshold": 0.85,
    "phashThreshold": 8,
    "proxyConfiguration": {
        "useApifyProxy": true
    },
    "maxCandidates": 12,
    "incrementalMonitorMode": false,
    "monitorStateName": "default",
    "customId": ""
};

// Run the Actor and wait for it to finish
const run = await client.actor("getascraper/reverse-image-search-monitor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "sourceImage": "https://raw.githubusercontent.com/github/explore/main/topics/react/react.png",
    "mode": "discover",
    "targetImages": [],
    "comparisonMode": "both",
    "similarityThreshold": 0.85,
    "phashThreshold": 8,
    "proxyConfiguration": { "useApifyProxy": True },
    "maxCandidates": 12,
    "incrementalMonitorMode": False,
    "monitorStateName": "default",
    "customId": "",
}

# Run the Actor and wait for it to finish
run = client.actor("getascraper/reverse-image-search-monitor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "sourceImage": "https://raw.githubusercontent.com/github/explore/main/topics/react/react.png",
  "mode": "discover",
  "targetImages": [],
  "comparisonMode": "both",
  "similarityThreshold": 0.85,
  "phashThreshold": 8,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "maxCandidates": 12,
  "incrementalMonitorMode": false,
  "monitorStateName": "default",
  "customId": ""
}' |
apify call getascraper/reverse-image-search-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,getascraper/reverse-image-search-monitor"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/5RMQSYLeJDninvuBb/builds/j5VT8FyvsZUMGEX5Z/openapi.json
