skills/05-kthorn-research-superpower/research/finding-open-access-papers/SKILL.md
Use Unpaywall API to find free full-text versions of paywalled papers
npx skillsauth add brycewang-stanford/Awesome-Agent-Skills-for-Empirical-Research Finding Open Access PapersInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Use Unpaywall to find legally available open access versions of papers that appear to be behind paywalls.
Core principle: Many paywalled papers have free versions (preprints, author manuscripts, institutional repositories). Unpaywall finds them.
Use this skill when:
Use BEFORE giving up on full text access
Simple REST API - no authentication required for reasonable usage
curl "https://api.unpaywall.org/v2/DOI?email=YOUR_EMAIL"
Parameters:
DOI - The paper's DOI (URL-encoded if needed)email - User's email (required, for courtesy/contact)IMPORTANT: Ask user for their email at the start of research session. Do NOT use placeholder emails like [email protected] or [email protected].
Example:
curl "https://api.unpaywall.org/v2/10.1038/[email protected]"
{
"doi": "10.1038/nature12373",
"title": "Paper Title",
"is_oa": true,
"best_oa_location": {
"url": "https://europepmc.org/articles/pmc3858213",
"url_for_pdf": "https://europepmc.org/articles/pmc3858213?pdf=render",
"version": "publishedVersion",
"license": "cc-by",
"host_type": "repository"
},
"oa_locations": [
{
"url": "https://europepmc.org/articles/pmc3858213",
"version": "publishedVersion"
},
{
"url": "https://arxiv.org/abs/1234.5678",
"version": "submittedVersion"
}
]
}
is_oa (boolean)
true - Open access version availablefalse - No free version foundbest_oa_location (object or null)
oa_locations (array)
version types:
publishedVersion - Final published version (best)acceptedVersion - Author's accepted manuscript (good)submittedVersion - Preprint before peer review (useful)# Try DOI first
curl -L "https://doi.org/10.1234/example.2023"
# If paywall detected (403, subscription required, etc):
curl "https://api.unpaywall.org/v2/10.1234/[email protected]"
# Parse JSON response
response=$(curl -s "https://api.unpaywall.org/v2/DOI?email=EMAIL")
# Check if OA available
is_oa=$(echo $response | jq -r '.is_oa')
if [ "$is_oa" = "true" ]; then
# Get best PDF URL
pdf_url=$(echo $response | jq -r '.best_oa_location.url_for_pdf // .best_oa_location.url')
# Download
curl -L -o "papers/paper.pdf" "$pdf_url"
fi
When OA found:
⚠️ Paper behind paywall at publisher
✓ Found open access version via Unpaywall!
Source: Europe PMC (published version)
PDF: https://europepmc.org/articles/pmc3858213?pdf=render
→ Downloading...
When no OA found:
⚠️ Paper behind paywall at publisher
✗ No open access version found via Unpaywall
Options:
- Request via institutional access
- Contact authors for preprint
- Continue with abstract only
If multiple locations available:
Priority order:
publishedVersion from publisher or PMCacceptedVersion from institutional repositorysubmittedVersion from preprint server (arXiv, bioRxiv)Add to full text fetching workflow:
Stage 2: Fetch Full Text
Try in order:
A. PubMed Central (free full text)
B. DOI resolution → If paywall, try Unpaywall
C. Unpaywall direct lookup
D. Preprints (bioRxiv, arXiv)
Updated workflow:
# 1. Try PMC
pmc_result=$(curl "https://eutils.ncbi.nlm.nih.gov/...")
if has_pmc_fulltext; then
fetch_pmc
exit 0
fi
# 2. Try DOI
doi_result=$(curl -L "https://doi.org/$doi")
if is_paywall; then
# 3. Try Unpaywall
unpaywall_result=$(curl "https://api.unpaywall.org/v2/$doi?email=$EMAIL")
if has_oa; then
fetch_unpaywall_pdf
exit 0
fi
fi
# 4. No full text available
report_no_fulltext
Free tier (with email):
Best practices:
import requests
import time
def find_open_access(doi, email):
"""
Find open access version via Unpaywall
Returns: (pdf_url, version, source) or (None, None, None)
"""
url = f"https://api.unpaywall.org/v2/{doi}"
params = {"email": email}
try:
response = requests.get(url, params=params, timeout=10)
response.raise_for_status()
data = response.json()
if not data.get('is_oa'):
return None, None, None
best_loc = data.get('best_oa_location')
if not best_loc:
return None, None, None
pdf_url = best_loc.get('url_for_pdf') or best_loc.get('url')
version = best_loc.get('version', 'unknown')
source = best_loc.get('host_type', 'unknown')
return pdf_url, version, source
except Exception as e:
print(f"Error checking Unpaywall for {doi}: {e}")
return None, None, None
# Usage
doi = "10.1038/nature12373"
pdf_url, version, source = find_open_access(doi, "[email protected]")
if pdf_url:
print(f"Found {version} at {source}")
print(f"PDF: {pdf_url}")
# Download PDF
response = requests.get(pdf_url)
with open(f'papers/{doi.replace("/", "_")}.pdf', 'wb') as f:
f.write(response.content)
else:
print("No open access version found")
time.sleep(0.1) # Rate limiting
Repositories:
Preprint servers:
Publisher sites:
DOI not found:
{
"error": "true",
"message": "DOI not found"
}
→ Check DOI format, try alternative identifiers
Network errors:
Malformed response:
is_oa fieldoa_locations array if best_oa_location missing| Task | Command |
|------|---------|
| Check if OA available | curl "https://api.unpaywall.org/v2/DOI?email=EMAIL" |
| Get best PDF URL | Parse .best_oa_location.url_for_pdf |
| List all OA sources | Parse .oa_locations[] |
| Check version type | Look at .version field |
| Download PDF | curl -L -o paper.pdf "$pdf_url" |
Called by:
evaluating-paper-relevance - When full text not in PMCanswering-research-questions - For highly relevant papersUpdates:
papers-reviewed.json - Note if OA foundSUMMARY.md - Include OA source infoUsing placeholder email: Using [email protected] or [email protected] → Ask user for their real email
Not including email: Required parameter, requests will fail
Checking every paper: Only check when needed (score ≥7, no PMC)
Ignoring version type: Published version better than preprint
Single source only: Check oa_locations array for alternatives
No rate limiting: Add delays even though no hard limit
Successful when:
After finding OA version:
tools
Recommend AND run open-source AI tools, agents, Claude Code / Codex skills, and MCP servers for any stage of a literature review — searching, reading, extracting, synthesizing, screening, citation-checking, and paper writing. Use when the user asks "what tool should I use to..." OR "install/run/use <tool> to ..." for research/lit-review work: automating a survey or related-work section, PDF→Markdown extraction for LLMs (MinerU/marker/docling), PRISMA / systematic review (ASReview), citation-backed Q&A over PDFs (PaperQA2), wiring papers into Claude/Cursor via MCP (arxiv/paper-search/zotero servers), or chatting with a Zotero library. Ships a launcher (scripts/litrun.py) that installs each tool in an isolated venv and runs it. Curated catalog of 70+ vetted projects. 支持中英文(用于「文献综述工具选型」与「一键安装/运行」)。
development
Route empirical-research requests through the Auto-Empirical Research Skills catalog when this whole repository is installed as one skill in Codex, CodeBuddy, Claude Code, or another IDE. Use to choose and load the right vendored AERS skill for causal inference, econometrics, replication, data acquisition, manuscript writing, peer review and referee responses, citation checking, de-AIGC editing, or full empirical-paper workflows without reading the entire repository at once.
documentation
Use when the project collects primary data or runs a field, lab, or survey experiment, before the intervention begins — write the pre-analysis plan, size the sample from a power calculation, and register with the AEA RCT Registry. Apply after the design is chosen in aer-identification and before any outcome data are seen.
tools
Guide economists to authoritative data sources with explicit, confirmed data specifications before retrieval; interfaces with Playwright MCP to navigate portals and extract real data, not articles about data.