| name | policyengine-python-client |
| description | ONLY use this skill when users explicitly ask about the PolicyEngine Python package installation,
REST API endpoints, API authentication, rate limits, or policyengine.py client library.
DO NOT use for household benefit/tax calculations — ALWAYS use policyengine-us or policyengine-uk instead.
This skill is about the API/client tooling itself, not about calculating benefits or taxes.
|
PolicyEngine Python Client
IMPORTANT: Always use the current year (2026) in situation dictionaries and calculate() calls, not 2024 or 2025.
This skill covers programmatic access to PolicyEngine for analysts and researchers.
Installation
pip install policyengine
pip install policyengine-us
Quick Start: Python Client
from policyengine import Simulation
household = {
"people": {
"you": {
"age": {"2026": 30},
"employment_income": {"2026": 50000}
}
},
"households": {
"your household": {
"members": ["you"],
"state_name": {"2026": "CA"}
}
}
}
sim = Simulation(situation=household, country_id="us")
income_tax = sim.calculate("income_tax", "2026")
For Users: Why Use Python?
Web app limitations:
- ✅ Great for exploring policies interactively
- ❌ Can't analyze many households at once
- ❌ Can't automate repetitive analyses
- ❌ Limited customization of charts
Python benefits:
- ✅ Analyze thousands of households in batch
- ✅ Automate regular policy analysis
- ✅ Create custom visualizations
- ✅ Integrate with other data sources
- ✅ Reproducible research
For Analysts: Common Workflows
Workflow 1: Calculate Your Own Taxes
from policyengine import Simulation
household = {
"people": {
"you": {
"age": {"2026": 35},
"employment_income": {"2026": 75000},
"qualified_dividend_income": {"2026": 5000},
"charitable_cash_donations": {"2026": 3000}
},
"spouse": {
"age": {"2026": 33},
"employment_income": {"2026": 60000}
},
"child1": {"age": {"2026": 8}},
"child2": {"age": {"2026": 5}}
},
}
sim = Simulation(situation=household, country_id="us")
federal_income_tax = sim.calculate("income_tax", "2026")
state_income_tax = sim.calculate("state_income_tax", "2026")
ctc = sim.calculate("ctc", "2026")
eitc = sim.calculate("eitc", "2026")
print(f"Federal income tax: ${federal_income_tax:,.0f}")
print()
()
()
Workflow 2: Analyze a Policy Reform
from policyengine import Simulation
reform = {
"gov.irs.credits.ctc.amount.base_amount": {
"2026-01-01.2100-12-31": 5000
}
}
household = create_household()
sim_baseline = Simulation(situation=household, country_id="us")
sim_reform = Simulation(situation=household, country_id="us", reform=reform)
ctc_baseline = sim_baseline.calculate("ctc", "2026")
ctc_reform = sim_reform.calculate("ctc", "2026")
print(f"CTC baseline: ${ctc_baseline:,.0f}")
print(f"CTC reform: ${ctc_reform:,.0f}")
print(f"Increase: ${ctc_reform - ctc_baseline:,.0f}")
Workflow 3: Batch Analysis
import pandas as pd
from policyengine import Simulation
households = [
{"income": 30000, "children": 0},
{"income": 50000, "children": 2},
{"income": 100000, "children": 3},
]
results = []
for h in households:
situation = create_household(income=h["income"], num_children=h["children"])
sim = Simulation(situation=situation, country_id="us")
results.append({
"income": h["income"],
"children": h["children"],
"income_tax": sim.calculate("income_tax", "2026"),
"ctc": sim.calculate("ctc", "2026"),
"eitc": sim.calculate("eitc", "2026")
})
df = pd.DataFrame(results)
print(df)
Using the REST API Directly
Authentication
Public access:
- 100 requests per minute (unauthenticated)
- No API key needed for basic use
Authenticated access:
Key Endpoints
Calculate household impact:
import requests
url = "https://api.policyengine.org/us/calculate"
payload = {
"household": household_dict,
"policy_id": reform_id
}
response = requests.post(url, json=payload)
result = response.json()
Get policy details:
response = requests.get("https://api.policyengine.org/us/policy/12345")
policy = response.json()
Get parameter values:
response = requests.get(
"https://api.policyengine.org/us/parameter/gov.irs.credits.ctc.amount.base_amount"
)
parameter = response.json()
For Full API Documentation
OpenAPI spec: https://api.policyengine.org/docs
To explore:
curl https://api.policyengine.org/docs
curl -X POST https://api.policyengine.org/us/calculate \
-H "Content-Type: application/json" \
-d '{"household": {...}}'
Limitations and Considerations
Rate Limits
Unauthenticated:
- 100 requests/minute
- Good for exploratory analysis
Authenticated:
- 1,000 requests/minute
- Required for production use
Data Privacy
- PolicyEngine does not store household data
- All calculations happen server-side and are not logged
- Reform URLs are public (don't include personal info in reforms)
Performance
API calls:
- Simple household: ~200-500ms
- Population impact: ~5-30 seconds (varies by reform)
- Use caching for repeated calculations
Local simulation (policyengine-us):
- Faster for batch analysis
- No rate limits
- No network dependency
- Limited to one country per package
Choosing Local vs API
Use Local (policyengine-us package)
When:
- Batch analysis of many households
- Need offline capability
- Analyzing parameter sweeps (axes)
- Development/testing
Install:
pip install policyengine-us
pip install policyengine-uk
Example:
from policyengine_us import Simulation
sim = Simulation(situation=household)
Use API (policyengine or requests)
When:
- Multi-country analysis
- Using latest model version
- Don't want to manage dependencies
- Integration with web services
Example:
import requests
response = requests.post("https://api.policyengine.org/us/calculate", ...)
For Contributors: Understanding the Client
Repository: PolicyEngine/policyengine.py
To see implementation:
git clone https://github.com/PolicyEngine/policyengine.py
cat policyengine/simulation.py
cat policyengine/api.py
Architecture:
Simulation class wraps API calls
calculate() method handles caching
- Transparent fallback between API and local
Advanced: Direct Country Package Usage
For maximum control and performance, use country packages directly:
from policyengine_us import Simulation
situation = {
}
sim = Simulation(situation=situation)
result = sim.calculate("variable_name", 2026)
Benefits:
- No API dependency
- Faster (no network)
- Full access to all variables
- Use axes for parameter sweeps
See policyengine-us-skill for detailed patterns.
Examples and Tutorials
PolicyEngine documentation:
Example notebooks:
- Repository: PolicyEngine/analysis-notebooks
- See policyengine-analysis-skill for analysis patterns
Community examples:
- Blog posts: policyengine.org/us/research
- GitHub discussions: github.com/PolicyEngine discussions
Getting Help
For usage questions:
For bugs:
- File issues in appropriate repo (policyengine-us, policyengine.py, etc.)
For collaboration: