AnswerLineStart free

, Google · SERP API · Tutorials · Brand Monitoring

Content theft detection with exact-match search queries

The simplest reliable way to detect copied content is to search for your own sentences. Pick a few distinctive sentences from each page, run each one as an exact-match query in quotes, exclude your own domains, and every result that remains is a page containing your exact words. Run that on a schedule and you have a content theft monitor that needs no crawler and no index of the web.

Exact-match search is precise but incomplete; the table below shows what it catches and what it misses.

Why exact-match search works

Scraper sites and content farms usually republish text verbatim or with light edits, because rewriting at scale costs them money. Search engines index those copies like any other page. Google treats a phrase in double quotes as an exact match; its Refine Google searches help page documents quotes for exact words or phrases, - to leave a word out and site: to limit to a site or domain (checked 2026-09-17). The minus and site: combine: -site:example.com removes your own pages.

A sentence of a dozen specific words is effectively unique on the web. If a page other than yours contains it, that page almost certainly derives from your text, directly or through someone who copied you.

What this approach catches and misses

Case Detected?
Verbatim full-article copies Yes, if indexed
Partial copies that keep some sentences intact Yes, if a fingerprint sentence survives
Syndicated or licensed republication Yes (you then allowlist it)
Light edits (synonyms swapped in some sentences) Partly: more fingerprints per page raises the odds
Paraphrased or AI-rewritten copies Rarely
Translations No, unless you fingerprint in the target language
Copies not indexed by Google, or behind logins No
Copied images or video No: this is a text method

Use it as a high-precision detector for the common case, and accept that rewritten theft needs different tools.

Step 1: choose fingerprint sentences

Fingerprint quality decides precision. Good fingerprints are:

A simple selection heuristic you can automate:

import re

STOP = set("the a an and or of to in for on with is are was were be by as at it this that from".split())

def sentences(text):
    return [s.strip() for s in re.split(r"(?<=[.!?])\s+", text) if s.strip()]

def score(s):
    words = re.findall(r"[A-Za-z0-9'%-]+", s)
    if not 8 <= len(words) <= 15 or '"' in s:
        return 0
    rare = [w for w in words if w.lower() not in STOP]
    digits = sum(any(c.isdigit() for c in w) for w in words)
    capitals = sum(w[0].isupper() for w in words[1:])
    return len(rare) + 2 * digits + capitals

def fingerprints(body, per_page=3):
    sents = sentences(body)[2:]  # skip the intro
    if not sents:
        return []
    thirds = [sents[i * len(sents) // per_page:(i + 1) * len(sents) // per_page] for i in range(per_page)]
    picks = [max(part, key=score) for part in thirds if part]
    return [p.rstrip(".!?") for p in picks if score(p) > 0]

Review the picks for your most valuable pages by hand once. Strip characters that commonly change when text is copied, such as curly quotes and trailing punctuation.

Step 2: build the queries

One query per fingerprint:

"the exact fingerprint sentence goes here" -site:example.com -site:blog.example.com

Add a -site: term for each domain you own and for known licensed partners you do not want to see again. Keep the exclusion list short; it is cheaper to filter known domains in code after the results come back, and it keeps the query readable in your logs.

Step 3: run the checks through the API

A single check:

curl -X POST https://api.answerline.dev/v1/monitor/google \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "\"median onboarding time fell from 41 to 12 days after the change\" -site:example.com",
    "country": "US"
  }'

The response’s result.organicResults[] lists every page Google showed, with position, title, link, displayedLink, snippet and date. For exact-match queries on unique sentences, the list is usually short or empty, and an empty list is the good outcome.

For a whole site, submit async tasks in batches of up to 500 with a webhook. Use the article id, fingerprint index and month in the idempotency key so a rerun of the job does not create duplicate tasks:

import hashlib, os, requests

API = "https://api.answerline.dev"
HEADERS = {"Authorization": f"Bearer {os.environ['API_KEY']}"}
OWN = ["example.com", "blog.example.com"]

def query_for(fp):
    return f'"{fp}" ' + " ".join(f"-site:{d}" for d in OWN)

def build_tasks(articles, month):
    for a in articles:
        for i, fp in enumerate(a["fingerprints"]):
            yield {
                "taskType": "GOOGLE",
                "payload": {"query": query_for(fp), "country": "US"},
                "idempotencyKey": f"theft:{a['id']}:{i}:{month}",
                "webhook": {"url": "https://hooks.example.com/theft"},
            }

def submit(articles, month):
    tasks = list(build_tasks(articles, month))
    for i in range(0, len(tasks), 500):
        r = requests.post(f"{API}/v1/async/task/batch", json=tasks[i:i + 500], headers=HEADERS, timeout=60)
        r.raise_for_status()

Keep a table mapping each fingerprint to its article id, so the webhook handler can look up which page a hit belongs to. See async tasks and webhooks for the delivery details.

If you publish in several markets, run the same fingerprints with the country and hl for each market: a copy aimed at a regional audience may rank there and not in the US results.

Step 4: score the candidates

Every result that survives your domain filter is a candidate. Score before a person looks:

Signal How to read it Weight
Fingerprint in snippet Google highlighted the matched text: strong evidence High
Several fingerprints from one article hit the same domain Likely a full copy High
Domain on your licensed or syndication allowlist Expected; log and skip Suppress
Domain is a known aggregator of quotes (forums, Q&A) Possibly a short quotation with a link Low
Page title matches your article title Wholesale copy Medium
Page date earlier than your publish date Check who copied whom Flag

Group candidates by domain and article. A domain that matches all three fingerprints of 40 of your articles is a scraper operation and deserves one case, not 120 tickets.

from urllib.parse import urlsplit

def host(url):
    return (urlsplit(url).hostname or "").lower().removeprefix("www.")

def candidates(article_id, fp, organic, allowlist):
    for r in organic:
        h = host(r["link"])
        if h in OWN or h in allowlist:
            continue
        yield {
            "article_id": article_id,
            "domain": h,
            "url": r["link"],
            "title": r.get("title"),
            "snippet_match": fp.lower()[:40] in (r.get("snippet") or "").lower(),
        }

Step 5: confirm and collect evidence

Before any action, a reviewer should confirm the copy and record evidence:

  1. Open the candidate URL and confirm the copied passage is there, not only in the search snippet from an older version.
  2. Save a dated capture of the page. The search result’s link, title and snippet and the task id are useful supporting records; request include.html if you want the results page itself retained.
  3. Record your original: its URL, publish date, and ideally a public archive capture that predates the copy.
  4. Check the license position: syndication agreements, guest-post terms, press kits and quotes with attribution are not theft.
  5. Note whether the copy links back, carries a canonical tag to your page, or names you. That changes the conversation.

Step 6: choose a response

Responses escalate from cheapest to most formal:

Situation Typical first response
Legitimate site, copied without permission, no attribution Contact the site; ask for removal or attribution and a canonical link
Syndication partner copying beyond the agreement Raise it with the partner contact under the agreement
Anonymous scraper site Notify the hosting provider, and consider a search engine removal request
Copy outranking your original Removal request, and review why your page is not the one shown

For Google specifically, its DMCA page (checked 2026-09-17) explains that copyright removal notices are submitted through its legal troubleshooter, per product. It warns that you can be liable for damages if you materially misrepresent that material is infringing, notes that the affected site can file a counter notification, and says Google may forward notices to Lumen, which publishes them after removing certain personal information. Take that warning seriously: a notice sent against a licensed partner or a fair quotation is a real risk.

Whether a given copy infringes, and which remedies apply in your jurisdiction, are legal questions. Talk to counsel before formal notices at scale. This article is not legal advice.

Step 7: watch where copies surface in AI answers

Copied content does not only compete in blue links. If a copy is cited in Google’s AI Overview for a query your article targets, the scraper gets the citation instead of you.

For your key queries, request the AI Overview and compare cited domains with your candidate list:

{
  "query": "how to reduce onboarding time",
  "country": "US",
  "include": { "aioverview": { "markdown": false } }
}

Read result.aioverview.citationPills[].domain and result.aioverview.sources[].url. A domain that appears both there and in your theft candidates is the highest-priority case. The AI Overview adds 2 credits to the Google Search task. For the broader picture of citations, see how AI engines choose citations and mentions vs citations.

Scheduling and cost

Copies tend to appear soon after publication, when the article is fresh in feeds and sitemaps, so weight checks toward new content:

Content age Cadence
Published in the last 30 days Weekly
1 to 12 months Monthly
Older, still high-traffic Quarterly
Older, low value Once, then stop

Credits: a Google Search async task is 3 credits; a sync call is 2 more; an AI Overview adds 2. Example for a site with 400 articles, 3 fingerprints each:

Segment Articles Checks per month Credits
New (weekly) 20 20 × 3 × 4 = 240 720
1–12 months (monthly) 180 540 1,620
Older high-traffic (quarterly) 60 60 180
Total 260 840 2,520

Check plan sizes on the pricing page. The free tier’s 500 credits a month covers about 166 checks, enough to fingerprint your top 50 articles and see what turns up.

Pitfalls

The same monitoring pattern protects brand assets in other ways: see typosquatting detection for lookalike domains, brand monitoring tools for the tool landscape, and the brand protection use case.

Run your first exact-match check from the quickstart or see the Google Search engine page.

Questions

How do I find out if someone copied my article?

Take two or three distinctive sentences from the article, search each as an exact phrase in quotes while excluding your own domain with -site:, and review the pages that come back. Automating that per article and per week turns it into a monitor.

Which sentences make the best fingerprints?

Mid-length sentences, roughly 8 to 15 words, that contain specific nouns, numbers or unusual phrasing and appear in the body rather than the title or intro. Avoid boilerplate, quotations from other sources and common phrases.

Will exact-match search find every copy?

No. It only finds copies that the search engine has indexed and chooses to show for that phrase, and it misses copies that were reworded or translated. Treat it as a high-precision detector for verbatim copies, not a complete census.

What can I do once I find a copy?

Check whether it is licensed or syndicated first. If it is not, common options are contacting the site, asking for attribution or a canonical link, notifying the host, or filing a copyright removal request with the search engine. For legal decisions, consult a lawyer; this article is not legal advice.

What does monitoring cost with this API?

Each Google Search async task costs 3 credits. Checking 3 fingerprints for each of 200 articles once a month is 600 tasks, or 1,800 credits.

Try it on your own prompts

500 free credits a month, no card. One POST returns the answer, sources and citations as JSON.

Keep reading