NBER APInber.org ↗
Search and retrieve NBER working papers by topic, program, or keyword. Access titles, abstracts, authors, DOIs, and publication dates via 2 REST endpoints.
What is the NBER API?
The NBER API exposes 2 endpoints for searching and retrieving National Bureau of Economic Research publications. Use search_papers to query across working papers, articles, books, and other content types with filters for topic, program, and sort order, or use get_paper to fetch a specific working paper's full abstract, author list with profile URLs, associated programs, DOI, and issue date by paper number.
curl -X GET 'https://api.parse.bot/scraper/1f177605-b040-467e-91e7-65b6a1d40fc4/search_papers?query=machine+learning&sort_by=relevance&per_page=5' \ -H 'X-API-Key: $PARSE_API_KEY'
Typed, relational, agent-ready
A generated client with real types, enums, and the links between objects — the structure a flat JSON response can't carry. Autocompletes in your editor and reads cleanly to coding agents.
- Fully typed · autocompletes
- Objects link to objects
- Typed errors & pagination
Typed Python client. Set up the SDK in your uv project, then pull this API’s typed client:
uv add parse-sdk uv run parse init uv run parse add --marketplace nber-org-api
uv run parse add --marketplace pulls a pinned snapshot of this canonical API — it won’t change underneath you. To customize it, subscribe and swap to your own copy.
"""
NBER Papers API Client
Practical example for searching and retrieving NBER research papers.
Get your API key from: https://parse.bot/settings
"""
import os
import requests
from typing import Optional, List, Dict, Any
class ParseClient:
"""Client for interacting with the NBER Papers API via Parse."""
def __init__(self, api_key: Optional[str] = None):
"""Initialize the Parse client.
Args:
api_key: API key for Parse. If not provided, reads from PARSE_API_KEY env var.
"""
self.base_url = "https://api.parse.bot"
self.scraper_id = "1f177605-b040-467e-91e7-65b6a1d40fc4"
self.api_key = api_key or os.getenv("PARSE_API_KEY")
if not self.api_key:
raise ValueError("API key not provided and PARSE_API_KEY environment variable not set")
def _call(self, endpoint: str, method: str = "POST", **params) -> Dict[str, Any]:
"""Make a request to the Parse API.
Args:
endpoint: The endpoint name (e.g., 'search_papers', 'get_paper')
method: HTTP method ('GET' or 'POST')
**params: Query/body parameters for the request
Returns:
JSON response from the API
Raises:
requests.HTTPError: If the request fails
"""
url = f"{self.base_url}/scraper/{self.scraper_id}/{endpoint}"
headers = {
"X-API-Key": self.api_key,
"Content-Type": "application/json"
}
if method.upper() == "GET":
response = requests.get(url, headers=headers, params=params)
elif method.upper() == "POST":
response = requests.post(url, headers=headers, json=params)
else:
raise ValueError(f"Unsupported HTTP method: {method}")
response.raise_for_status()
return response.json()
def search_papers(
self,
query: str = "",
page: int = 1,
per_page: int = 20,
content_type: str = "working_paper",
topic: Optional[str] = None,
program: Optional[str] = None,
sort_by: str = "date"
) -> Dict[str, Any]:
"""Search NBER papers with filtering and pagination.
Args:
query: Search query for relevance ranking
page: Page number (1-based)
per_page: Results per page (20, 50, or 100)
content_type: Content type filter (working_paper, chapter, article, etc.)
topic: Topic filter (e.g., 'Macroeconomics', 'Labor Economics')
program: Program filter (e.g., 'Monetary Economics', 'Labor Studies')
sort_by: Sort order ('date' or 'relevance')
Returns:
Search results with papers list and pagination info
"""
params = {
"query": query,
"page": page,
"per_page": per_page,
"content_type": content_type,
"sort_by": sort_by
}
if topic:
params["topic"] = topic
if program:
params["program"] = program
return self._call("search_papers", method="GET", **params)
def get_paper(self, paper_id: str) -> Dict[str, Any]:
"""Get detailed information for a specific NBER paper.
Args:
paper_id: Working paper ID (e.g., 'w10567' or '10567')
Returns:
Detailed paper information including abstract, authors, and programs
"""
return self._call("get_paper", method="GET", paper_id=paper_id)
def print_paper_summary(paper: Dict[str, Any]) -> None:
"""Print a formatted summary of a paper."""
title = paper.get('title', 'N/A')
paper_id = paper.get('paper_number', 'N/A')
date = paper.get('date', paper.get('issue_date', 'N/A'))
print(f"\n 📄 {title}")
print(f" ID: {paper_id} | Date: {date}")
if paper.get('authors'):
authors = ", ".join([a['name'] for a in paper['authors']])
print(f" Authors: {authors}")
if paper.get('abstract'):
abstract = paper['abstract']
if len(abstract) > 120:
abstract = abstract[:120] + "..."
print(f" Abstract: {abstract}")
def print_detailed_paper(paper: Dict[str, Any]) -> None:
"""Print detailed information about a paper."""
print(f"\n{'='*80}")
print(f"📋 DETAILED PAPER INFORMATION")
print(f"{'='*80}")
print(f"Title: {paper['title']}")
print(f"Paper Number: {paper['paper_number']}")
print(f"Issue Date: {paper['issue_date']}")
print(f"DOI: {paper['doi']}")
print(f"URL: {paper['url']}")
if paper.get('authors'):
print(f"\nAuthors ({len(paper['authors'])}):")
for author in paper['authors']:
print(f" • {author['name']}")
if paper.get('programs'):
print(f"\nAssociated Programs:")
for program in paper['programs']:
print(f" • {program}")
if paper.get('abstract'):
print(f"\nAbstract:")
print(f"{paper['abstract']}")
def main():
"""Demonstrate a practical workflow for the NBER Papers API."""
client = ParseClient()
print("\n" + "="*80)
print("NBER PAPERS API - RESEARCH DISCOVERY WORKFLOW")
print("="*80)
# Workflow: Search for papers on a topic, then get details on papers of interest
print("\n📚 STEP 1: Searching for papers on 'machine learning'...")
search_results = client.search_papers(
query="machine learning",
per_page=5,
sort_by="relevance"
)
total_found = search_results.get('total_results', 0)
current_page = search_results.get('page', 1)
total_pages = search_results.get('total_pages', 1)
print(f"\n✓ Found {total_found:,} papers matching 'machine learning'")
print(f" Showing page {current_page} of {total_pages}")
print(f" ({len(search_results.get('papers', []))} papers on this page)")
papers = search_results.get('papers', [])
if not papers:
print("\n❌ No papers found. Exiting.")
return
print(f"\n📖 Recent papers from search results:")
for i, paper in enumerate(papers, 1):
print(f"\n [{i}] {paper.get('title', 'N/A')[:70]}...")
print(f" Type: {paper.get('type', 'N/A')} | Date: {paper.get('date', 'N/A')}")
# Drill down into the first paper for detailed info
first_paper = papers[0]
paper_id = first_paper.get('paper_number')
if paper_id:
print(f"\n" + "="*80)
print(f"📌 STEP 2: Fetching detailed information for paper {paper_id}...")
print("="*80)
detailed_paper = client.get_paper(paper_id)
print_detailed_paper(detailed_paper)
# Secondary workflow: Search by topic and program
print(f"\n" + "="*80)
print("📚 STEP 3: Searching papers by specific topic and program...")
print("="*80)
print("\n Searching for 'Labor Economics' papers in 'Labor Studies' program...")
topic_results = client.search_papers(
topic="Labor Economics",
program="Labor Studies",
per_page=3,
sort_by="date"
)
topic_papers = topic_results.get('papers', [])
print(f"\n✓ Found {topic_results.get('total_results', 0)} papers in this category")
print(f" Showing {len(topic_papers)} most recent papers:\n")
for i, paper in enumerate(topic_papers, 1):
print(f" [{i}]", end="")
print_paper_summary(paper)
# Demonstrate pagination
if topic_results.get('total_pages', 1) > 1:
print(f"\n" + "="*80)
print("📄 STEP 4: Demonstrating pagination...")
print("="*80)
print("\n Fetching page 2 of Labor Economics results...")
page_2_results = client.search_papers(
topic="Labor Economics",
program="Labor Studies",
page=2,
per_page=3,
sort_by="date"
)
page_2_papers = page_2_results.get('papers', [])
print(f"✓ Retrieved page {page_2_results.get('page')} with {len(page_2_papers)} papers:\n")
for i, paper in enumerate(page_2_papers, 1):
print(f" [{i}]", end="")
print_paper_summary(paper)
print(f"\n" + "="*80)
print("✅ WORKFLOW COMPLETED SUCCESSFULLY!")
print("="*80)
print("\n💡 You can now:")
print(" • Search papers by keyword, topic, or program")
print(" • Filter by content type (working papers, articles, etc.)")
print(" • Navigate through paginated results")
print(" • Get detailed information for papers of interest")
print(" • Access author profiles, DOIs, and abstracts")
print()
if __name__ == "__main__":
main()Search NBER papers with filtering by content type, topic, or program. Supports pagination and sorting. The query parameter influences relevance ranking; use content_type, topic, or program facets for filtering.
| Param | Type | Description |
|---|---|---|
| page | integer | Page number (1-based). |
| query | string | Search query for relevance ranking. |
| topic | string | Topic filter (e.g., Macroeconomics, Labor Economics, Financial Economics). Use %COMMA% for commas in topic names. |
| program | string | Program filter (e.g., Monetary Economics, Labor Studies, Corporate Finance). |
| sort_by | string | Sort order. Accepted values: date, relevance. |
| per_page | integer | Results per page. Accepted values: 20, 50, or 100. |
| content_type | string | Content type filter. Accepted values: working_paper, chapter, article, conference, book, video, center_paper, dataset. |
{
"type": "object",
"fields": {
"page": "integer, current page number",
"query": "string or null, the search query used",
"papers": "array of paper objects with title, authors, abstract, date, paper_number, url, doi, type, new_this_week",
"sort_by": "string, sort order used",
"per_page": "integer, results per page",
"total_pages": "integer, total number of pages",
"total_results": "integer, total matching papers"
},
"sample": {
"data": {
"page": 1,
"query": "machine learning",
"papers": [
{
"doi": "10.3386/w31285",
"url": "https://www.nber.org/papers/w31285",
"date": "May 2023",
"type": "Working Paper",
"title": "The Economics of Financial Stress",
"authors": [
{
"name": "Dmitriy Sergeyev",
"profile_url": "https://www.nber.org/people/dmitriy_sergeyev"
}
],
"abstract": "We study the psychological costs of financial constraints...",
"paper_number": "w31285",
"new_this_week": false
}
],
"sort_by": "relevance",
"per_page": 20,
"total_pages": 1784,
"total_results": 35673
},
"status": "success"
}
}About the NBER API
Search NBER Publications
The search_papers endpoint accepts an optional query string for relevance ranking and supports facet filters via content_type (e.g., working_paper, chapter, book, video), topic (e.g., Macroeconomics, Labor Economics), and program (e.g., Monetary Economics, Corporate Finance). Results can be sorted by date or relevance, and page size is configurable to 20, 50, or 100 results. Each item in the papers array includes title, authors, abstract, date, paper_number, url, doi, type, and a new_this_week flag. Pagination metadata — total_results, total_pages, and current page — is returned alongside the results.
Retrieve Individual Papers
The get_paper endpoint accepts a working paper ID either with or without the w prefix (e.g., w10567 or 10567) and returns a single paper object. The response includes the full abstract, an authors array where each entry has both name and profile_url, a programs array listing associated NBER research programs, the canonical paper_number with w prefix, issue_date as a month-and-year string, doi, and the direct url to the paper page.
Coverage and Content Types
NBER publishes working papers across dozens of research programs covering macroeconomics, finance, labor, health, and more. The search_papers endpoint surfaces not just working papers but also chapters, conference materials, center papers, and videos hosted on nber.org. The new_this_week boolean on each search result lets you identify recently released papers without sorting manually by date.
The NBER API is a managed, monitored endpoint for nber.org — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when nber.org changes and a check fails, the API is automatically queued for repair and re-verified. It is built to keep working as the site underneath it changes.
This isn't an official nber.org API — it's an independent, maintained REST wrapper over public data. Where the source has no official API (or only a limited one), Parse gives you a stable contract over a source that never promised one, and keeps it current. Need a new endpoint or field? You can revise it yourself in plain English and the agent rebuilds it against the live site in minutes — contributing the change back to the shared API is free.
Will this API break when the source site changes?+
Is this an official API from the source site?+
Can I fix or extend this API myself if I need a new endpoint or field?+
What happens if I call an endpoint that has an issue?+
- Monitor newly released NBER working papers by filtering
search_papersoncontent_type=working_paperand checking thenew_this_weekfield. - Build a literature review tool that queries papers by
topic(e.g.,Financial Economics) and exportsdoiandabstractfields for citation management. - Track research output by NBER program using the
programfilter (e.g.,Labor Studies) and paginate through full result sets. - Enrich an academic database with author profile URLs and associated programs by calling
get_paperfor each known paper number. - Surface related NBER research in an economics news application by searching on a keyword
querysorted bydate. - Aggregate paper metadata — titles, DOIs, issue dates — for bibliometric analysis across multiple content types.
| Tier | Price | Credits/month | Rate limit |
|---|---|---|---|
| Free | $0/mo | 100 | 5 req/min |
| Hobby | $30/mo | 1,000 | 20 req/min |
| Developer | $100/mo | 5,000 | 100 req/min |
One credit = one API call regardless of which marketplace API you call. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.
Does NBER have an official public developer API?+
What does `get_paper` return beyond what `search_papers` includes?+
get_paper returns the full abstract, individual author profile_url links, and a programs array listing the NBER research programs associated with the paper. The search_papers endpoint returns a truncated view of these fields suitable for listing and filtering, while get_paper is the authoritative source for a single paper's complete metadata.Can I filter search results by author name?+
search_papers endpoint does not expose a dedicated author filter. You can include an author name in the general query parameter for relevance-ranked results, but there is no strict author facet. You can fork this API on Parse and revise it to add an author-scoped filter endpoint.Does the API return full PDF download links for papers?+
url field pointing to the paper's page on nber.org and a doi identifier, but does not return direct PDF download URLs. NBER restricts full-text PDF access to subscribers. You can fork this API on Parse and revise it to surface any publicly accessible download links where they exist.How should I handle topic names that contain commas?+
topic parameter uses %COMMA% as a placeholder for literal commas in topic names. Standard URL-encoded commas may be interpreted as list separators, so substitute any commas in the topic string with %COMMA% before sending the request.