When I first needed bank transactions inside a Python app, I did what every developer does. I typed pip install open-banking and hoped for the best. What I found instead was a drawer full of half-maintained wrappers, each tied to one commercial provider. This is the map I wish somebody had handed me back then.
Quick disclosure so you can calibrate my bias: I maintain open-banking.io, a low-cost EU/UK bank-data API. This piece is about the whole landscape, not one product.
What a search for an open banking Python library actually finds
Search PyPI for "open banking" and you get a small pile of packages. The one literally named openbankingapi is thin and hasn't seen meaningful work in years. enablebanking-api is a generated SDK for Enable Banking's commercial API. There are also several community wrappers for the old Nordigen API, none of them official, and most went quiet after GoCardless absorbed Nordigen and rebranded everything under Bank Account Data.
The bigger aggregators do ship real SDKs. Plaid has plaid-python, maintained and fine, but its European coverage has always felt like the B-side of a US-first product. TrueLayer's truelayer-python is decent too, though the company has drifted steadily upmarket toward enterprise clients.
None of these packages is wrong. But none of them is what "open banking Python library" sounds like either. They're all clients for one company's REST API, and the company can vanish or reprice right underneath them. Ask anyone who built on the Nordigen free tier.
Why there's no "requests" of open banking
The dream library would talk to every bank directly. In Europe that can't exist, and the reason is regulatory more than technical.
PSD2 forces thousands of banks to expose APIs, but each bank implements its own flavor, and calling them as a third party requires an eIDAS certificate most indie devs will never want to obtain. So the market settled on aggregators: licensed intermediaries that maintain one clean REST API over hundreds of banks. All the ugly per-bank work happens on their servers.
That's why every Python package you find wraps exactly one aggregator. The aggregator is the library. Python is just the steering wheel.
The three realistic options
Given that, you really have three choices:
- Use your provider's official SDK if one exists. Fine, but you inherit their abstractions and their release cadence.
- Use a community wrapper. Check the last-commit date first; half of these are weekend projects wearing a README.
- Write ~60 lines of
requestsagainst the provider's REST API yourself. My usual pick. You understand every line, and switching providers later becomes a base-URL change instead of a rewrite.
I've done all three on real projects. The third ages best.
A minimal client in plain requests
Most aggregator APIs follow the same shape: list banks, start a consent flow, read accounts, read transactions. Here's the entire pattern, anonymized:
import requests
BASE = "https://api.your-ais-provider.example/v2"
H = {"Authorization": "Bearer YOUR_TOKEN"} # from the provider's dashboard
# 1. Find the user's bank
banks = requests.get(f"{BASE}/banks/", headers=H).json()["results"]
bank_id = next(b for b in banks if "YourBank" in b["name"])["id"]
# 2. Start a consent (requisition) flow — user approves at their bank
req = requests.post(f"{BASE}/requisitions/", headers=H, json={
"redirect": "http://localhost:8000/callback",
"institution_id": bank_id,
}).json()
print("Send the user to:", req["link"])
# 3. After they approve and land back on your redirect:
accounts = requests.get(f"{BASE}/requisitions/{req['id']}/", headers=H).json()["accounts"]
tx = requests.get(f"{BASE}/accounts/{accounts[0]}/transactions/", headers=H).json()
That's the core loop for basically every European open banking provider. If a library saves you less code than this, ask what it's actually adding.
The part no library saves you from
The loop above is the easy 20%. The annoying 80% is lifecycle management, and no pip package handles it for you.
PSD2 consents expire — in most countries the user has to re-authenticate roughly every 90 days. Bank connections also break for mundane reasons: password changes, bank maintenance windows, silent schema drift on one specific bank's transaction format. You'll want a small job that checks connection health and tells the user which bank needs attention, in plain language.
Refresh tokens are the other quiet time sink. They expire on their own schedule, per provider, and the failure mode is always a 401 at 2am rather than a clean error. Whatever you build, wrap it in one retry-with-re-auth path early. That's the code I wish I'd written on day one instead of week six.
This is exactly where writing your own thin module pays off. The failure modes are your product decisions, not the library's.
What I check before depending on any of this
Before committing to a provider, and by extension to a library, I look at four things.
Bank coverage in the countries I actually need. Aggregate bank counts are marketing. The list for your two target countries is reality.
Whether the sandbox works without paperwork. If I can't test end-to-end before talking to a sales team, that tells me everything about who the product is really for.
Pricing per bank connection. This varies wildly, from enterprise contracts down to entry tiers around €3/month at the low end. For an indie project, this number decides viability more than any API design choice.
Who holds the keys. Some providers keep everything server-side; others let you hold your own private key so plaintext account data never touches their infrastructure. Worth knowing that option exists before you need it.
What I'd pick
If you just want to see it work this weekend, pick a provider with a no-friction sandbox and write the 60 lines of requests yourself. I wrote a longer walkthrough of doing exactly that with Python — no certificates, real transactions at the end — if you want the full version: reading EU bank transactions with Python and PSD2.
Then wrap those calls in one small module of your own. Congratulations, you now have a private open banking Python library. One you fully control, and one that survives whatever the aggregator market decides to do next.
Top comments (0)