This plagiarism checker finds public web pages that share sentences with your text, with a similarity score and the matching passage for each page. It is a Python CLI. This page shows a stored sample; there is no hosted demo.
The problem
You have an essay, an article or a product description and want to know whether parts of it already appear on the public web. Pasting sentences into a search box one by one is slow. You also need a score you can compare, the passage that matched and a record of what each check cost.
What the app does
- Samples the most distinctive sentences of a file, stdin or inline text.
- Searches the web for each sentence and scores every returned snippet.
- Fetches the best candidate pages once and compares them with every sampled sentence.
- Writes a matches CSV, a sentences CSV and a Markdown summary with grouped sources.
- Shows a plan and cost estimate first, and stops above a cost limit you set.
The tool gives no verdict and does not detect AI writing. Only sampled sentences are checked, and only pages the search returns are compared. A match does not establish who wrote the wording first.
How it works
- Sample sentences. The CLI splits the text at sentence punctuation, skips short sentences and picks up to 8 that have the most substantial words. Long sentences are shortened to their most distinctive window of up to 18 words.
- Search. The default engine sends each sentence as a quoted query to
GET /web. Thesearchengine usesPOST /searchwith page text instead. It costs more per sentence and can miss very new pages. - Score snippets. Text is normalized for Unicode, case and punctuation. An exact match scores 1. Otherwise the score is the share of the sentence's word triples found in the snippet.
- Verify pages. Up to 3 top pages per sentence, and 10 per run, are fetched with
GET /web/extractas plain text. Each page is scored against every sampled sentence at no extra cost. - Report. Matches at or above the threshold (0.6 by default) go to the CSV with the URL, score, longest shared word run and a passage of about 200 characters. The summary groups mirror URLs under one source.
The code
This verbatim excerpt from plagiarism_checker.py scores one result. It relies on difflib, re and the normalize helper defined in the full file.
def score_result(sentence, result):
page = result.get('page_text') or ' '.join(result.get('highlights') or [])
a, b = normalize(sentence).split(), normalize(page).split()
exact = bool(a) and ' '.join(a) in ' '.join(b)
n = 3 if len(a) >= 3 else 2
grams = [tuple(a[i:i+n]) for i in range(len(a)-n+1)]
pagegrams = {tuple(b[i:i+n]) for i in range(len(b)-n+1)}
containment = sum(g in pagegrams for g in grams) / len(grams) if grams else 0.0
run = difflib.SequenceMatcher(None, a, b, autojunk=False).find_longest_match()
# Map normalized words back to original character offsets for readable passages.
offsets = []
for match in re.finditer(r'\w+', page, re.UNICODE):
offsets.extend([match.start()] * len(normalize(match.group()).split()))
start = offsets[run.b] if run.b < len(offsets) else 0
start = max(0, start - 70)
snippet = page[start:start+200]
return dict(score=1.0 if exact else containment, exact=exact, containment=containment,
longest_run_words=run.size, longest_run_share=run.size/len(a) if a else 0,
evidence_snippet=snippet)Endpoints
GET /webGET /web/extractPOST /search
Example output
From the source README, a run on samples/mixed-essay.txt on 2026-10-24. The sample text mixes original sentences with one encyclopedia sentence, one public-domain book sentence and one paraphrase.
Matching sources found on the web
3 of 7 sampled sentences have at least one matching public page (42.9%).
Total cost: $0.010000 USD; 14 calls; slowest 2.95 s; empty-result calls 0 ($0.000000).When no sampled sentence matches, the report says so and adds that this does not prove the text is original.
Run it yourself
Get the Python examples and open the plagiarism checker folder. Use Python 3.9 or newer. Create an API key in the console. The CLI reads the key only from a private file: set DESEARCH_KEY_FILE or use the default ~/.desearch_api_key.
git clone https://github.com/Desearch-ai/desearch-py-examples
cd desearch-py-examples/plagiarism-checker
python3 -m venv .venv
. .venv/bin/activate
python -m pip install -r requirements.txtThese commands are copied from the source README. The first shows the plan and estimate without a key or network.
python plagiarism_checker.py essay.txt --dry-run
python plagiarism_checker.py essay.txt --yes --out output --run-name essay-check
python plagiarism_checker.py --text 'Carefully designed gardens support diverse flowering plants throughout the summer.' --yesUse --max-sentences, --verify-pages and --max-cost to limit a run. --replay rebuilds reports from saved responses with no new calls.
What it costs
The 2026-10-24 sample run made 7 searches and 7 page fetches. Six fetches were billed and one returned 404 at $0. The total was $0.010, read from X-Desearch-Cost-Usd response headers.
The default estimate uses $0.001 per web search and $0.0005 per page extraction, so 8 sentences with page checks stay well under the default --max-cost of $0.25. These are dated measurements and list rates, not current price quotes. Check pricing before a larger run.
Ideas to extend it
- Run the checker on every new article before it goes live and keep the summary with the draft.
- Compare two runs of the same text to see which matching pages are new.
- Add a review step that opens each matching page next to its passage.
- Raise
--max-sentencesfor long documents and set--max-costto match.
