Summary
HVB / UniCredit (hbci-01.hypovereinsbank.de) with appTAN does not work with python-fints 5.0.0. Along the way to diagnosing why, I found four distinct issues in the library that are worth fixing individually, plus one structural gap that blocks HVB entirely. This extends (and narrows down) the unresolved #135.
Tested on python-fints 5.0.0 (latest release at time of writing), Python 3.14, macOS.
What works
- Product ID
9FA6681DEC0CF3046BFC2F8A6 is registered with HVB and gets through dialog init.
- Dialog init returns
0020 Dialoginitialisierung erfolgreich without emitting any HITAN challenge; init_tan_response stays None.
- TAN mechanisms are discovered correctly: one mechanism advertised,
security_function=904 appTAN-Verfahren (HKTAN version 6).
What doesn't — four separate issues
1. WAF blocks the default python-requests User-Agent (HTTP 403)
FinTSHTTPSConnection uses a bare requests.session() with no custom User-Agent. HVB's edge returns HTTP 403 with a static HTML body Request Failed … support ID … for the python-requests default UA. A browser UA (Mozilla/5.0 …) returns HTTP 500 from the FinTS app layer instead, i.e., the WAF is UA-filtering. This is what #135 was hitting but the trail went cold before anyone identified the cause.
Repro:
curl -sI -X POST https://hbci-01.hypovereinsbank.de/bank/hbci \
-H "Content-Type: text/plain" --data "x"
# → HTTP 403 Forbidden, body: "Request Failed … support ID …"
curl -sI -X POST https://hbci-01.hypovereinsbank.de/bank/hbci \
-H "Content-Type: text/plain" -H "User-Agent: Mozilla/5.0" --data "x"
# → HTTP 500 (app layer, no WAF block)
Suggested fix: allow callers to set a User-Agent via a kwarg on FinTS3PinTanClient (or FinTSHTTPSConnection), or default to a non-"python-requests" UA — the current default is getting classified as bot traffic by HVB and likely other banks on similar WAF stacks.
Workaround (works):
client.connection.session.headers["User-Agent"] = "Mozilla/5.0 …"
2. _bootstrap_mode is never reset to False when is_tan_media_required() is False
In FinTS3PinTanClient.__init__ (client.py:1263), _bootstrap_mode = True. It's only flipped to False inside get_tan_media() (client.py:1682). For banks where is_tan_media_required() returns False (e.g., HVB appTAN — single mechanism, supported_media_number = 1), get_tan_media() is never called, so _bootstrap_mode stays True for the entire client lifetime.
Consequence: in _process_response (client.py:1611–1616):
if response.code == '9075':
if self._bootstrap_mode: # ← still True
if self._standing_dialog:
self._standing_dialog.open = False # silently close
else:
raise FinTSSCARequiredError(...)
the SCA-required signal is silently swallowed. The caller then sees a misleading FinTSNoResponseError: response did not contain a response because the subsequent find_segments(HISPA1, throw=True) has nothing to find in the closed dialog.
Suggested fix: either set _bootstrap_mode = False at the end of FinTS3PinTanClient.__init__ once initial mechanism/media setup is expected to be driven by the caller, or expose an explicit client.finish_bootstrap() that minimal_interactive_cli_bootstrap calls. As it stands, the silent-swallow path only triggers for banks not requiring media selection, which is exactly the modern PSD2 / single-mechanism case.
Workaround:
client._bootstrap_mode = False # after minimal_interactive_cli_bootstrap
3. After (2) is worked around, HVB replies 9075 at HIRMG (dialog) level for every real operation
Once _bootstrap_mode=False surfaces the real error, every call — get_sepa_accounts(), get_transactions(), or a standalone HKTAN(process='4', segment_type=HKSPA) — produces the same 9075 Dialog abgebrochen - starke Authentifizierung erforderlich at HIRMG level. No HITAN segment, no 0030/3955 on tan_seg.
I tried four variants:
| Variant |
segment_type |
Other |
Result |
| A |
HKSPA |
standalone HKTAN |
9075 at HIRMG |
| B |
HKSPA, tan_medium_name=None |
standalone HKTAN |
9075 at HIRMG |
| C |
None |
standalone HKTAN |
9075 at HIRMG |
| D |
HKSPA |
HKSPA + HKTAN bundled |
9075 at HIRMG |
_need_twostep_tan_for_segment correctly returns False for HKSPA (HIPINS says tan_required=False on HKSPA) and True on HKKAZ, so the library's default behaviour matches BPD. But HVB's runtime PSD2 enforcement rejects everything without SCA, including operations the BPD itself says don't need it.
This is the structural issue: python-fints doesn't currently have a recovery path from a dialog-level 9075. It can only handle a 0030/3955 challenge on a tan_seg. When HVB closes the dialog instead of issuing HITAN, there's no built-in way to drive the SCA. It's not clear from the FinTS spec what a client is supposed to do here — HVB's behaviour looks like a proprietary pre-SCA requirement that neither tries to challenge nor allows anonymous-auth operations.
Request: is there a known pattern other clients (aqbanking, Subsembly) use to satisfy HVB here? A standalone "Anmeldung mit TAN" HKTAN at a specific point in the dialog? If so, implementing that would unblock HVB. If not, at least document #135 as "bank requires out-of-spec SCA bootstrap, not currently supported".
4. (Minor) Default UA concern
As noted in (1), even banks that aren't HVB may WAF-filter python-requests/X.Y.Z as bot traffic. A non-default UA would increase baseline compatibility with minimal effort.
Environment
- python-fints 5.0.0 (installed via uv, fresh env)
- Python 3.14.0
- macOS 14 (Darwin 25.3.0)
- Bank: UniCredit Bank GmbH (HypoVereinsbank), BLZ 70020270
- TAN method: appTAN (mobile app push confirmation) — only one mechanism advertised
- HBCI URL:
https://hbci-01.hypovereinsbank.de/bank/hbci
References
Summary
HVB / UniCredit (
hbci-01.hypovereinsbank.de) with appTAN does not work with python-fints 5.0.0. Along the way to diagnosing why, I found four distinct issues in the library that are worth fixing individually, plus one structural gap that blocks HVB entirely. This extends (and narrows down) the unresolved #135.Tested on python-fints 5.0.0 (latest release at time of writing), Python 3.14, macOS.
What works
9FA6681DEC0CF3046BFC2F8A6is registered with HVB and gets through dialog init.0020 Dialoginitialisierung erfolgreichwithout emitting any HITAN challenge;init_tan_responsestaysNone.security_function=904 appTAN-Verfahren(HKTAN version 6).What doesn't — four separate issues
1. WAF blocks the default
python-requestsUser-Agent (HTTP 403)FinTSHTTPSConnectionuses a barerequests.session()with no customUser-Agent. HVB's edge returns HTTP 403 with a static HTML bodyRequest Failed … support ID …for the python-requests default UA. A browser UA (Mozilla/5.0 …) returns HTTP 500 from the FinTS app layer instead, i.e., the WAF is UA-filtering. This is what #135 was hitting but the trail went cold before anyone identified the cause.Repro:
Suggested fix: allow callers to set a
User-Agentvia a kwarg onFinTS3PinTanClient(orFinTSHTTPSConnection), or default to a non-"python-requests" UA — the current default is getting classified as bot traffic by HVB and likely other banks on similar WAF stacks.Workaround (works):
2.
_bootstrap_modeis never reset to False whenis_tan_media_required()is FalseIn
FinTS3PinTanClient.__init__(client.py:1263),_bootstrap_mode = True. It's only flipped to False insideget_tan_media()(client.py:1682). For banks whereis_tan_media_required()returns False (e.g., HVB appTAN — single mechanism,supported_media_number = 1),get_tan_media()is never called, so_bootstrap_modestaysTruefor the entire client lifetime.Consequence: in
_process_response(client.py:1611–1616):the SCA-required signal is silently swallowed. The caller then sees a misleading
FinTSNoResponseError: response did not contain a responsebecause the subsequentfind_segments(HISPA1, throw=True)has nothing to find in the closed dialog.Suggested fix: either set
_bootstrap_mode = Falseat the end ofFinTS3PinTanClient.__init__once initial mechanism/media setup is expected to be driven by the caller, or expose an explicitclient.finish_bootstrap()thatminimal_interactive_cli_bootstrapcalls. As it stands, the silent-swallow path only triggers for banks not requiring media selection, which is exactly the modern PSD2 / single-mechanism case.Workaround:
3. After (2) is worked around, HVB replies
9075at HIRMG (dialog) level for every real operationOnce
_bootstrap_mode=Falsesurfaces the real error, every call —get_sepa_accounts(),get_transactions(), or a standaloneHKTAN(process='4', segment_type=HKSPA)— produces the same9075 Dialog abgebrochen - starke Authentifizierung erforderlichat HIRMG level. No HITAN segment, no0030/3955on tan_seg.I tried four variants:
segment_typeHKSPA9075at HIRMGHKSPA,tan_medium_name=None9075at HIRMGNone9075at HIRMGHKSPAHKSPA + HKTANbundled9075at HIRMG_need_twostep_tan_for_segmentcorrectly returns False for HKSPA (HIPINS saystan_required=Falseon HKSPA) and True on HKKAZ, so the library's default behaviour matches BPD. But HVB's runtime PSD2 enforcement rejects everything without SCA, including operations the BPD itself says don't need it.This is the structural issue: python-fints doesn't currently have a recovery path from a dialog-level
9075. It can only handle a0030/3955challenge on a tan_seg. When HVB closes the dialog instead of issuing HITAN, there's no built-in way to drive the SCA. It's not clear from the FinTS spec what a client is supposed to do here — HVB's behaviour looks like a proprietary pre-SCA requirement that neither tries to challenge nor allows anonymous-auth operations.Request: is there a known pattern other clients (aqbanking, Subsembly) use to satisfy HVB here? A standalone "Anmeldung mit TAN" HKTAN at a specific point in the dialog? If so, implementing that would unblock HVB. If not, at least document #135 as "bank requires out-of-spec SCA bootstrap, not currently supported".
4. (Minor) Default UA concern
As noted in (1), even banks that aren't HVB may WAF-filter
python-requests/X.Y.Zas bot traffic. A non-default UA would increase baseline compatibility with minimal effort.Environment
https://hbci-01.hypovereinsbank.de/bank/hbciReferences
not_plannedafter reporter couldn't test further; this issue picks up that trail.