orizn
Official Python SDK for the Orizn Visa API.
Visa requirements for 39,999 passport-destination pairs, in 15 languages, with up to 32 data points per visa — fees, processing times, photo specs, transit visas, embassies, overstay penalties, safety advisories.
Install
pip install orizn
Quick start
from orizn import Orizn
# Free key, 10 seconds, no credit card → https://visa.orizn.app/visa-api
client = Orizn(api_key="orizn_visa_...") # or: export ORIZN_API_KEY=...
r = client.check("FRA", "JPN")
print(r.requirement) # "visa_free"
print(r.visa_free_days) # 90
visa = client.get_visa("USA", "CHN", lang="fr") # all 15 languages, free plan included
print(visa.description)
print(visa.documents_required)
print(visa.process)
That runs as-is once ORIZN_API_KEY is set. Every visa endpoint needs a key — the free
tier is 50 requests/month (5 until you confirm your email).
Get a key
| Free key, instant | https://visa.orizn.app/visa-api |
| Upgrade to Hobby — $9/mo, 10,000 req | billing |
| Plan | Price | Requests/month |
|---|---|---|
| Free | $0 | 50 |
| Hobby | $9 | 10,000 |
| Starter | $49 | 30,000 |
| Pro | $199 | 250,000 |
| Business | $699 | 1,000,000 |
All 15 languages are available on every plan, free included. What paid plans add is volume and the extended data points (fees, transit, embassies, safety, …).
Methods
| Method | Auth | Description |
|---|---|---|
check(passport, destination) |
Key | Requirement, visa-free days, last-verified date |
get_visa(passport, destination, lang="en") |
Key | Full record — up to 32 data points |
bulk(passport, destinations, lang="en") |
Key (Hobby+) | Up to 25 destinations in one call |
stats() |
None | Public coverage statistics |
bulk() requires an explicit list of destinations (max 25 per call), and each destination
returned counts as one request against your quota.
for row in client.bulk("FRA", ["JPN", "USA", "THA"]):
print(row.destination, row.requirement, row.visa_free_days)
The client is a context manager, so the HTTP session gets closed:
with Orizn() as client:
print(client.check("DEU", "BRA").requirement)
Errors
Four typed exceptions, each carrying the URL that unblocks you:
from orizn import OriznAuthError, OriznForbiddenError, OriznRateLimitError, OriznNotFoundError
try:
visa = client.get_visa("FRA", "JPN")
except OriznAuthError: # 401 — no key. Message links to the free key page.
...
except OriznForbiddenError: # 403 — invalid key, or plan too low for this call.
...
except OriznRateLimitError as e: # 429 — quota spent. e.retry_after when the API sends it.
...
except OriznNotFoundError: # 404 — no data for that pair.
...
All four subclass OriznError, which also covers timeouts and connection failures.
Bad country codes and unsupported languages raise ValueError before the request goes out —
the API bills a request before validating params, so a typo would otherwise cost you quota.
What's in get_visa()
Fields your plan doesn't include come back as None.
Core (always present)
| Field | Type | Description |
|---|---|---|
passport / destination |
str |
ISO 3166-1 alpha-3 |
requirement |
VisaRequirement |
visa_free | visa_required | e_visa | visa_on_arrival | eta | no_admission |
visa_free_days |
int | None |
Max visa-free stay, in days |
visa_required |
bool |
True if any visa formality applies |
description |
str |
Localized summary |
documents_required |
list[str] |
Documents to bring/submit |
process |
list[str] |
Step-by-step application process |
tips |
list[str] |
Travel tips |
visa_types |
list[VisaType] |
Visa categories available — name, cost, duration, description |
extension, processing_time, cost, validity, max_stay |
str | None |
Localized free-text details |
country_info |
CountryInfo |
Currency, language, timezone, capital |
verified |
bool |
Verified against an official source |
source |
str | None |
Where the record came from |
plan, remaining |
str | int | None |
Your plan and requests left, read from the response headers |
Extended intelligence (plan-gated)
| Field | Type | What it tells you |
|---|---|---|
transit_visa |
TransitVisa |
Transit rules + free transit hours at major hubs (DXB, IST, DOH, SIN, …) |
passport_validity_months |
int |
Minimum passport validity at entry |
visa_fee |
VisaFee |
Single- and multiple-entry cost, with currency |
processing_days |
ProcessingDays |
Standard / express / rush |
photo_specs |
PhotoSpecs |
Dimensions, background, glasses & head-covering rules |
vaccinations_required |
list[str] |
Mandatory vaccines |
insurance_required |
InsuranceRequired |
Minimum travel insurance coverage |
dual_nationality_warnings |
list[str] |
Warnings for dual nationals |
stamp_warnings |
list[str] |
Passport stamps that may block entry |
minor_rules |
MinorRules |
Rules for under-18s |
overstay_penalty |
OverstayPenalty |
Fine per day, max fine, criminal liability, and ban_duration — days keyed by scenario ({"under_30_days": 365, …}), since the API has no single number |
entry_by_mode |
EntryByMode |
air / land / sea, each the API's raw object (visa_free_days, esta_required, e_visa_available, … — the keys vary by pair) |
remote_work_visa |
RemoteWorkVisa |
Digital nomad visa availability, duration, fee |
extension_rules |
ExtensionRules |
Whether the stay can be extended, and how |
reciprocity_history |
list[ReciprocityChange] |
Past policy changes between the two countries |
safety |
SafetyInfo |
Advisory level (1–4), source, last update |
best_apply_period |
str |
Recommended application window |
health_requirements |
HealthRequirements |
Tests, vaccination proof, quarantine, screenings |
embassy |
EmbassyData |
Two lists of EmbassyInfo: your missions at the destination, and the destination's missions in your country (a country usually has an embassy plus consulates) |
visa = client.get_visa("FRA", "JPN")
if visa.visa_fee and visa.visa_fee.single_entry:
fee = visa.visa_fee.single_entry
print(f"Single entry: {fee.amount} {fee.currency}")
if visa.transit_visa:
for hub in visa.transit_visa.hubs:
print(f"{hub.airport} ({hub.city}): {hub.transit_free_hours}h transit-free")
if visa.safety:
print(f"Advisory level: {visa.safety.level}")
if visa.embassy:
for e in visa.embassy.visa_application_embassy: # where to apply
print(f"{e.name} ({e.city}) — {e.phone}")
print(visa.entry_by_mode.air.get("visa_free_days") if visa.entry_by_mode else None)
All types are exported: from orizn import VisaData, TransitVisa, EmbassyData, ....
Languages
fr en es pt de it ja ko zh ru ar hi th vi tl — the tuple is exported as orizn.LANGUAGES.
Tests
python tests/test_client.py # offline, no key
ORIZN_API_KEY=... python tests/test_client.py # + a live smoke test (~5 requests)
Offline, a fake session replays payloads captured from production. With a key set, the same
run also hits the real API, so a schema drift shows up instead of silently decoding to None.
Feedback
Building a travel agent or visa tool? Tell us what you need — api@orizn.app.
Links
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file orizn-1.2.0.tar.gz.
File metadata
- Download URL: orizn-1.2.0.tar.gz
- Upload date:
- Size: 20.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.14.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6500c383353d8a72c70db95935a121fc76fc2a61c5a0267f5b30f0c231684021
|
|
| MD5 |
1b708866e5929c90dad31108fb567543
|
|
| BLAKE2b-256 |
0474b5b3c733d75c36182e4b60a91225be97e2c9d77558709fbb18c8f191de24
|
File details
Details for the file orizn-1.2.0-py3-none-any.whl.
File metadata
- Download URL: orizn-1.2.0-py3-none-any.whl
- Upload date:
- Size: 16.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.14.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f17e965e450871ac8392bd5240317c41b0da1ffa3414f8d684571ca6dc1f0c88
|
|
| MD5 |
8f8ea46028f367a6d775dc9a524f8888
|
|
| BLAKE2b-256 |
5c4c21202862c5b87fb549eb10f177d17d746aa46bfaf3a27644efefa1e1b5dc
|