Prerequisites
You need three things:
- Python 3.8 or newer.
- The
requestslibrary. - A free API Ninjas API key — issued instantly, no credit card. If you already have an account, it's on your profile page.
pip install requestsStep 1: Fetch a year of holidays
The endpoint is /v1/holidays and takes a country (two-letter ISO code) and a year — future years included:
import requests
response = requests.get(
'https://api.api-ninjas.com/v1/holidays',
params={'country': 'US', 'year': 2026},
headers={'X-Api-Key': 'YOUR_API_KEY'},
timeout=10,
)
response.raise_for_status()
holidays = response.json()
for h in holidays[:3]:
print(f"{h['date']} {h['name']}")The request on the wire and the start of the response:
[
{
"country": "United States",
"iso": "US",
"year": 2026,
"date": "2026-01-01",
"day": "Thursday",
"name": "New Year's Day",
"type": "federal_holiday"
},
{
"country": "United States",
"iso": "US",
"year": 2026,
"date": "2026-01-19",
"day": "Monday",
"name": "Martin Luther King Jr. Day",
"type": "federal_holiday"
}
]Each entry carries an ISO date, the weekday name, the holiday name, and a type that classifies it.
Step 2: Filter by holiday type
Not every calendar entry closes the banks. The type field separates federal_holiday from observance and season, and the same values work as a request filter so you only fetch what you need:
import os
import requests
API_URL = 'https://api.api-ninjas.com/v1/holidays'
session = requests.Session()
session.headers['X-Api-Key'] = os.environ.get('API_NINJAS_KEY', 'YOUR_API_KEY')
def get_holidays(country: str, year: int, kind: str | None = None) -> list:
"""Return the holidays for one country and year, optionally one type."""
params = {'country': country, 'year': year}
if kind:
params['type'] = kind
response = session.get(API_URL, params=params, timeout=10)
response.raise_for_status()
return response.json()
for h in get_holidays('US', 2026, kind='federal_holiday'):
print(f"{h['date']} {h['day']:9} {h['name']}")Step 3: Find upcoming holidays
Dates arrive as ISO strings, so date.fromisoformat() turns the list into something you can compare against today:
from datetime import date
today = date.today()
holidays = get_holidays('US', today.year)
upcoming = [h for h in holidays if date.fromisoformat(h['date']) >= today]
print('Next 5 holidays:')
for h in upcoming[:5]:
print(f" {h['date']} {h['name']}")Step 4: Build a business-day check
The most common production use of holiday data is one boolean: does this date count? Load the federal holidays into a set once, and the check is two conditions:
from datetime import date
FEDERAL_2026 = {
date.fromisoformat(h['date'])
for h in get_holidays('US', 2026, kind='federal_holiday')
}
def is_business_day(d: date) -> bool:
return d.weekday() < 5 and d not in FEDERAL_2026
print(is_business_day(date(2026, 1, 1))) # False — New Year's Day
print(is_business_day(date(2026, 1, 2))) # TrueFrom here, “add three business days” is a small loop — walk forward one day at a time, counting only dates that pass is_business_day().
Step 5: Handle errors
Failures are the usual three — and note the caching advice in the 429 branch: a country-year of holidays is a fixed list, so you should rarely request the same one twice:
from requests.exceptions import HTTPError, RequestException
try:
holidays = get_holidays('US', 2026)
except HTTPError as error:
status = error.response.status_code
if status == 400:
print('Invalid country code or year')
elif status == 401:
print('Missing or invalid API key')
elif status == 429:
print('Rate limit exceeded — cache results, holidays rarely change')
else:
print(f'HTTP {status}: {error.response.text}')
except RequestException as error:
print(f'Network error: {error}')Where to go from here
If business-day math is the end goal, the Working Days API computes it directly. The Country API pairs well when you need metadata about the countries whose calendars you're fetching. The complete script is below.