If you want Japanese financial data in Python today, your options are: scrape Yahoo Finance Japan and hope the HTML doesn't change, pay ¥3M/year for a Bloomberg terminal, or spend two weeks writing an XBRL parser that handles three accounting standards and Shift-JIS encoding.
Or you can do this:
from axiora import Axiora
client = Axiora(api_key="your-key")
toyota = client.companies.retrieve_financials("7203", years=1)
print(f"Revenue: ¥{toyota.data[0].revenue:,}")
# Revenue: ¥29,929,992,000,000Toyota's audited revenue. Typed, auto-completed in your IDE, parsed from XBRL — not scraped from HTML. This tutorial shows you how to go from that first call to screening, comparing, and charting 4,125+ Japanese companies.
What You'll Need
- Python 3.9+
- An Axiora API key — free, no credit card, takes 30 seconds
pip install axioraThat's it. The SDK is generated by Stainless — the same tool that builds the SDKs for OpenAI, Anthropic, and Cloudflare. Typed Pydantic models for every response, automatic retries, pagination built in. No JSON wrangling.
Setup
from axiora import Axiora
client = Axiora(api_key="your-api-key")One import, one line. The client also reads AXIORA_API_KEY from your environment if you prefer not to hardcode it. All monetary values come back as JPY integers — no floats touching the money.
Get Any Company's Financials
Securities code 7203 — the same 4-digit ticker you see on the TSE:
financials = client.companies.retrieve_financials("7203", years=5)
for f in financials.data:
rev = f.revenue / 1_000_000_000_000
ni = f.net_income / 1_000_000_000_000
print(f" {f.fiscal_year} Rev: ¥{rev:.1f}T NI: ¥{ni:.2f}T") 2024 Rev: ¥29.9T NI: ¥4.94T
2023 Rev: ¥37.2T NI: ¥2.45T
2022 Rev: ¥31.4T NI: ¥2.85T
2021 Rev: ¥27.2T NI: ¥2.25T
2020 Rev: ¥29.9T NI: ¥2.08TFive years of Toyota's financials. Every number from an audited 有価証券報告書, parsed from XBRL and normalized across accounting standards. The response is a typed Pydantic model — f.revenue auto-completes in your IDE, no guessing field names from JSON.
The API also accepts EDINET codes (E02144). Both resolve to the same company.
Company Details
company = client.companies.retrieve("7203")
c = company.data
print(f"Name (JP): {c.name_jp}")
print(f"Name (EN): {c.name_en}")
print(f"EDINET: {c.edinet_code}")
print(f"Ticker: {c.securities_code}")
print(f"Sector: {c.sector}")Name (JP): トヨタ自動車株式会社
Name (EN): TOYOTA MOTOR CORPORATION
EDINET: E02144
Ticker: 7203
Sector: 輸送用機器Screen: Find What's Interesting
"Show me Japanese companies with ROE above 15% and revenue over ¥100 billion, sorted by ROE." One call:
screen = client.screen.retrieve(
roe_min=15.0,
revenue_min=100_000_000_000,
sort="roe_desc",
limit=10,
)
for r in screen.data:
name = r.company.name_en or r.company.name_jp
roe = r.metrics.roe
rev_b = r.financials.revenue / 1_000_000_000
print(f" {name[:30]:<30} ROE: {roe:.1f}% Rev: ¥{rev_b:,.0f}B")The underlying data is the same — audited EDINET filings. Bloomberg gives you a terminal with real-time prices, news, and a thousand other things. But for screening by fundamentals from annual reports, you don't need one.
Filter by roe_min, roe_max, revenue_min, revenue_max, net_income_min, roa_min, sector, and more. Sort by any metric, ascending or descending.
Compare Competitors
Toyota (7203), Honda (7267), Nissan (7201) — side by side:
codes = ["7203", "7267", "7201"]
for code in codes:
company = client.companies.retrieve(code)
financials = client.companies.retrieve_financials(code, years=3)
print(f"\n{company.data.name_en}")
for f in financials.data:
rev = f.revenue / 1_000_000_000_000
ni = f.net_income / 1_000_000_000
print(f" {f.fiscal_year} Rev: ¥{rev:.1f}T NI: ¥{ni:,.0f}B")Six API calls, three companies, three years each. The numbers tell you Toyota is 2x Honda in revenue and 4x in profitability. Nissan is in a different situation entirely.
Chart: 10 Years of Revenue
Three companies, three very different growth stories. Toyota for scale, Sony for the turnaround, Keyence for compounding:
pip install axiora matplotlibfrom axiora import Axiora
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
client = Axiora() # reads AXIORA_API_KEY from env
companies = {"7203": "Toyota", "6758": "Sony", "6861": "Keyence"}
fig, ax = plt.subplots(figsize=(10, 6))
for code, label in companies.items():
financials = client.companies.retrieve_financials(code, years=10)
years = [f.fiscal_year for f in reversed(financials.data)]
rev = [f.revenue / 1e12 for f in reversed(financials.data)]
ax.plot(years, rev, marker="o", label=label, linewidth=2)
ax.set_ylabel("Revenue (¥ Trillion)")
ax.set_title("Toyota vs Sony vs Keyence — 10 Year Revenue")
ax.legend()
ax.grid(True, alpha=0.3)
ax.yaxis.set_major_formatter(mticker.FormatStrFormatter("¥%.0fT"))
plt.tight_layout()
plt.savefig("japan_revenue.png", dpi=150)Toyota dominates on scale. But look at the slopes. Keyence — a ¥2 trillion sensor company most people outside Japan haven't heard of — has been compounding revenue at 15%+ annually for a decade.
Growth Rates
Let's quantify that:
growth = client.companies.retrieve_growth("6861", years=10)
print("Keyence — YoY Revenue Growth")
for entry in growth.data.yoy:
g = entry.growth.revenue
if g is not None:
bar = "█" * int(abs(g))
sign = "+" if g >= 0 else ""
print(f" {entry.fiscal_year} {sign}{g:>6.1f}% {bar}")
cagr = growth.data.cagr
if cagr.api_5yr:
print(f"\n 5-Year CAGR: {cagr.api_5yr.revenue:.1f}%")CAGR, year-over-year, all pre-computed. Because you shouldn't need to do arithmetic on raw revenue numbers to answer "is this company growing?"
Sector Rankings
Highest ROE in electronics — Japan's most competitive sector:
ranking = client.rankings.retrieve(
"roe",
sector="電気機器",
limit=10,
)
for r in ranking.data:
name = (r.company.name_en or r.company.name_jp)[:35]
print(f" #{r.rank:<3} {name:<35} ROE: {r.value:.1f}%")Sector names are in Japanese (that's how EDINET classifies them): 電気機器 (electronics), 輸送用機器 (transport equipment), 情報・通信業 (IT/telecom), 銀行業 (banking).
Async Support
Building something concurrent? The SDK has a full async client:
import asyncio
from axiora import AsyncAxiora
async def main():
async with AsyncAxiora() as client:
# Fetch multiple companies in parallel
tasks = [
client.companies.retrieve_financials(code, years=5)
for code in ["7203", "6758", "6861", "9984", "6501"]
]
results = await asyncio.gather(*tasks)
for result in results:
f = result.data[0]
print(f" {f.edinet_code} Rev: ¥{f.revenue/1e12:.1f}T")
asyncio.run(main())Same typed responses, same error handling, just await everything.
Error Handling
The SDK raises typed exceptions:
from axiora import NotFoundError, RateLimitError
try:
client.companies.retrieve("INVALID")
except NotFoundError:
print("Company not found")
except RateLimitError as e:
print(f"Rate limited — retry after {e.response.headers.get('Retry-After')}s")No checking status codes. No parsing error JSON. Just catch and handle.
The Full Script
Everything above, copy-paste ready:
#!/usr/bin/env python3
"""Japanese financial data with Python — Axiora quick start."""
from axiora import Axiora
client = Axiora() # reads AXIORA_API_KEY from env
# Toyota financials
print("=== Toyota (7203) ===")
for f in client.companies.retrieve_financials("7203", years=5).data:
print(f" {f.fiscal_year} Rev: ¥{f.revenue/1e12:.1f}T NI: ¥{f.net_income/1e12:.2f}T")
# High-ROE screen
print("\n=== ROE > 15%, Revenue > ¥100B ===")
for r in client.screen.retrieve(
roe_min=15, revenue_min=100_000_000_000, sort="roe_desc", limit=10
).data:
name = (r.company.name_en or r.company.name_jp)[:30]
print(f" {name:<30} ROE: {r.metrics.roe:.1f}%")
# Electronics ranking
print("\n=== Electronics — Top ROE ===")
for r in client.rankings.retrieve("roe", sector="電気機器", limit=10).data:
name = (r.company.name_en or r.company.name_jp)[:30]
print(f" #{r.rank:<3} {name:<30} {r.value:.1f}%")
print("\nAll data: audited EDINET filings, XBRL-parsed.")Keep Going
- EDINET for Developers — where this data comes from and why extracting it is a pain
- How We Parse XBRL — the 570-line parser behind these numbers
Free tier. No credit card. No "contact sales." Get your API key →