Verify academic citations against CrossRef, Semantic Scholar, and OpenAlex. Detects AI-hallucinated references, chimeric citations (real title + wrong authors), and suspicious patterns before submission.
.bib file with AI assistancebash
python scripts/citation_checker.py references.bib
.bib Files in a Directory#bash
python scripts/citation_checker.py path/to/report/
bash
python scripts/citation_checker.py references.bib --json
bash
python scripts/citation_checker.py references.bib --verbose
Each citation is checked against three independent databases:
SourceCoverageStrengthCrossRef140M+ DOI-registered worksBest for journal/conference papers with DOIsSemantic Scholar200M+ papersBest author disambiguation, arXiv coverageOpenAlex240M+ worksBroadest coverage, fully open
Verification logic:
When a citation's title matches a real paper but the authors don't overlap at all, it's flagged as a possible chimeric hallucination — the most dangerous type because the title looks real on Google Scholar.
10.xxxx/)CodeMeaning0All citations verified1One or more citations not found2Suspicious citations only (no hard failures)
bash
pip install requests
No API keys required — uses free tiers of all three databases.
CategoryResultDescriptionKnown-good9/10 (90%)Famous ML papers (Vaswani, Devlin, Brown, He, etc.)Known-bad10/10 (100%)Fabricated papers with plausible titlesChimeric5/5 (100%)Real titles with wrong authors**False positive rate10%1 miss: unpublished tech report without DOIFalse negative rate0%**No fake paper was ever verified
The core guarantee: fake papers are never marked as real.
bash
#!/bin/bash
# .git/hooks/pre-commit
python scripts/citation_checker.py references.bib --json > /tmp/cite_check.json
NOT_FOUND=$(python3 -c "import json; d=json.load(open('/tmp/cite_check.json')); print(d['summary']['not_found'])")
if [ "$NOT_FOUND" -gt "0" ]; then
echo "BLOCKED: $NOT_FOUND unfound citations. Run 'python scripts/citation_checker.py references.bib --verbose' to investigate."
exit 1
fi
yaml
- name: Check citations
run: |
pip install requests
python scripts/citation_checker.py references.bib --json > citation_report.json
python -c "
import json, sys
r = json.load(open('citation_report.json'))
if r['summary']['not_found'] > 0:
print(f'FAIL: {r[\"summary\"][\"not_found\"]} citations not found')
sys.exit(1)
print(f'PASS: {r[\"summary\"][\"verified\"]} verified, {r[\"summary\"][\"suspicious\"]} suspicious')
"