You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Describe the bug
I wanted to log into my bank account via this app (https://flathub.org/apps/org.tabos.saldo).
The problem is that the TAN2Go procedure has been completely discontinued by the bank since 24.11.2024. There is only the pushTAN or chipTAN procedure left. However, since I have not activated or do not need a chipTAN via the bank, I can only access my account via the pushTAN procedure. Unfortunately, this option is not offered in the app. The author of this app has forwarded me to you and I should report the problem here.
*Bank I tested this with
Name of the bank: Deutsche Kreditbank Berlin (DKB) AG
FinTS URL: https://fints.dkb.de/fints
Expected behavior
Login to my Bank-Accout via App with the pushTAN procedure.
Can someone look into the problem and maybe do something about it?
Just wanted to add, that the Saldo App does work great with my DKB bank account via chipTAN.
I'd also appreciate to have TAN2Go pushTAN added but please don't break chipTAN on that way. ;)
edit: Apologies! I got the app-based methods mixed up.
Hi,
could someone provide a minimal working example?
Here is what I have:
from fints.client import FinTS3PinTanClient
from fints.client import FinTS3PinTanClient, NeedTANResponse
from fints.utils import minimal_interactive_cli_bootstrap
logger.info(f"get user / PIN for {bank_and_user}")
bank, account = get_credentials(bank_and_user)
logger.info(f"create")
client = FinTS3PinTanClient(
bank_identifier=bank["BLZ"], # 12030000
user_id=account["user_id"], # Your login name
pin=account["pin"], # Your banking PIN
server=bank["server"],
product_id=FINTS_PRODUCT_ID,
)
logger.info(f"fetch_tan_mechanisms")
client.fetch_tan_mechanisms()
mechanisms = client.get_tan_mechanisms()
mechanisms_map = {m.name: k for k, m in mechanisms.items()}
preference = 'DKB App'
if preference in mechanisms_map.keys():
preferred_id = mechanisms_map.get(preference)
else:
raise Exception(f"meachanism {preference} not offered (options are {mechanisms_map.keys()}")
logger.info(f"set preferred tan machanism {preference}")
client.set_tan_mechanism(preferred_id)
logger.info(f"enter with")
with client:
# Since PSD2, a TAN might be needed for dialog initialization. Let's check if there is one required
if client.init_tan_response:
print("A TAN is required:", client.init_tan_response.challenge)
if not isinstance(client.init_tan_response, NeedTANResponse):
print("No TAN is required")
else:
print("TAN is required")
# else: mobile TAN/manual Smart-TAN/... is used
if client.init_tan_response.decoupled:
tan = input('Please press enter after confirming the transaction in your app:')
else:
tan = input('Please enter TAN:')
transactions = client.send_tan(client.init_tan_response, tan)
else:
logger.info("no tan required")
# just for curiosity
info = client.get_information()
# Fetch accounts
accounts = client.get_sepa_accounts()
logger.info(f"accounts: {accounts}")
logger.info(f"DONE")
and I get this warning:
site-packages\fints\parser.py:163: FinTSParserWarning: Ignoring parser error and returning generic object: Wrong input when setting HNVSK3.security_identification_details. Turn off robust_mode to see Exception.
My App asks me for permission, I give that in mobile phone app and press Enter, but on the python side I get denied
[2025-04-27 00:42:23] ERROR Dialog response: 9050 - Teilweise liegen Fehler vor. [_log_response in client.py:346][fints.client]
[2025-04-27 00:42:23] ERROR Dialog response: 9210 - Auftrag abgelehnt [_log_response in client.py:346][fints.client]
[2025-04-27 00:42:23] ERROR Dialog response: 9800 - Dialog abgebrochen. [_log_response in client.py:346][fints.client]
[2025-04-27 00:42:23] ERROR Dialog response: 9050 - Teilweise liegen Fehler vor. [_log_response in client.py:346][fints.client]
[2025-04-27 00:42:23] ERROR Dialog response: 9210 - Auftrag abgelehnt [_log
_response in client.py:346][fints.client]
For some reason, the client.init_tan_response.decoupled is False - I have no idea where to look next. Do I have to enter the app-pin or something?
Hi, could someone provide a minimal working example? Here is what I have:
from fints.client import FinTS3PinTanClient
from fints.client import FinTS3PinTanClient, NeedTANResponse
from fints.utils import minimal_interactive_cli_bootstrap
logger.info(f"get user / PIN for {bank_and_user}")
bank, account = get_credentials(bank_and_user)
logger.info(f"create")
client = FinTS3PinTanClient(
bank_identifier=bank["BLZ"], # 12030000
user_id=account["user_id"], # Your login name
pin=account["pin"], # Your banking PIN
server=bank["server"],
product_id=FINTS_PRODUCT_ID,
)
logger.info(f"fetch_tan_mechanisms")
client.fetch_tan_mechanisms()
mechanisms = client.get_tan_mechanisms()
mechanisms_map = {m.name: k for k, m in mechanisms.items()}
preference = 'DKB App'
if preference in mechanisms_map.keys():
preferred_id = mechanisms_map.get(preference)
else:
raise Exception(f"meachanism {preference} not offered (options are {mechanisms_map.keys()}")
logger.info(f"set preferred tan machanism {preference}")
client.set_tan_mechanism(preferred_id)
logger.info(f"enter with")
with client:
# Since PSD2, a TAN might be needed for dialog initialization. Let's check if there is one required
if client.init_tan_response:
print("A TAN is required:", client.init_tan_response.challenge)
if not isinstance(client.init_tan_response, NeedTANResponse):
print("No TAN is required")
else:
print("TAN is required")
# else: mobile TAN/manual Smart-TAN/... is used
if client.init_tan_response.decoupled:
tan = input('Please press enter after confirming the transaction in your app:')
else:
tan = input('Please enter TAN:')
transactions = client.send_tan(client.init_tan_response, tan)
else:
logger.info("no tan required")
# just for curiosity
info = client.get_information()
# Fetch accounts
accounts = client.get_sepa_accounts()
logger.info(f"accounts: {accounts}")
logger.info(f"DONE")
and I get this warning:
site-packages\fints\parser.py:163: FinTSParserWarning: Ignoring parser error and returning generic object: Wrong input when setting HNVSK3.security_identification_details. Turn off robust_mode to see Exception.
My App asks me for permission, I give that in mobile phone app and press Enter, but on the python side I get denied
[2025-04-27 00:42:23] ERROR Dialog response: 9050 - Teilweise liegen Fehler vor. [_log_response in client.py:346][fints.client]
[2025-04-27 00:42:23] ERROR Dialog response: 9210 - Auftrag abgelehnt [_log_response in client.py:346][fints.client]
[2025-04-27 00:42:23] ERROR Dialog response: 9800 - Dialog abgebrochen. [_log_response in client.py:346][fints.client]
[2025-04-27 00:42:23] ERROR Dialog response: 9050 - Teilweise liegen Fehler vor. [_log_response in client.py:346][fints.client]
[2025-04-27 00:42:23] ERROR Dialog response: 9210 - Auftrag abgelehnt [_log
_response in client.py:346][fints.client]
For some reason, the client.init_tan_response.decoupled is False - I have no idea where to look next. Do I have to enter the app-pin or something?
Hi,
I'm having the same issue. It looks like DKB expects a TAN although the decoupled TAN option is beeing used. I tried to send a 4 or 6 digit dummy TAN but still the same issue. Was somesone confronted with the same problem and found a solution?
I traced the problem to the following lines in the dialog.py in init(), lines 87ff:
if tan_seg:
for resp in retval.responses(tan_seg):
if resp.code in ('0030', '3955'):
self.client.init_tan_response = NeedTANResponse(
None,
retval.find_segment_first('HITAN'),
'_continue_dialog_initialization',
self.client.is_challenge_structured(),
resp.code == '3955',
)
In my scenario DKB sends me the following Segments
HIRMS:3:2:5+3955::Sicherheitsfreigabe erfolgt über anderen Kanal+0030::Auftrag empfangen - Sicherheitsfreigabe erforderlich'
What happens is that the code first creates a NeedTANResponse with decoupled=True (5th parameter: resp.code == 3955) for the init_tan_response (this is what is needed), but overwrites it in the next loop (matching 0030) with decoupled=False (as resp.code != 3955).
And indeed either limiting the if resp.code statement to if resp.code == 3955 or extending the 5th parameter of the NeedTANRespone to resp.code in ('0030', '3955') both solves the problem for me and the linked test-script above works nice.
I can not really estimate which variant is right, as i have no experience with the FinTS yet. Personally i a actually working with extending resp.code in ('0030', '3955')
Also i would suggest a time.sleep(1) in the client.py after line 1370, so to not spam retrys to the server, and check "only" once in a sec, if the App-Auth worked ?
k... i just realized anyhow i debugged an old code.... the issue is already fixed on current master:
if tan_seg:
for resp in retval.responses(tan_seg):
if resp.code in ('0030', '3955'):
self.client.init_tan_response = NeedTANResponse(
None,
retval.find_segment_first('HITAN'),
'_continue_dialog_initialization',
self.client.is_challenge_structured(),
False,
)
if resp.code == '3955':
self.client.init_tan_response.decoupled = True
break
so no more issues for me...
edit: i just tried the script from @nefarius2001, it also works with the current github code. The latest "fints" Code (4.2.3 from Nov 2024) from PyPi however misses the fix for DKB.
Thanks a lot @jusernrone !
I replaced the pip-installed 4.2.3 release with a submodule-clone of the repo using the current master (3d3644d).
It works!
May I ask a follow-up question:
Is there an resonable way to poll (like every second) if the App-Approval has been commited?
Asking the user to press enter when being done feels - clumsy
(see the line in my script "Please press enter after confirming the transaction in your app:")
If the operation was not yet confirmed using the decoupled app, this method will again return a NeedTANResponse.
So you can loop until it no more returns an instance of it:
from time import sleep
...
looping_for_app_confirmation = False
while isinstance(client.init_tan_response, NeedTANResponse):
if looping_for_app_confirmation == True: sleep(1)
client.init_tan_response = client.send_tan(client.init_tan_response,None)
looping_for_app_confirmation = True
Perhaps it would even make sense to allow send_tan to not require a tan (for these decoupled auth-methods) and add a spam-protection for looping calls?
For other travellers: This is my code snippet called with client.init_tan_response and the result from client.get_transactions:
def handle_challenge( client, result_get ): if not isinstance(result_get, NeedTANResponse): logger.debug("No TAN is required") return result_get logger.info("TAN is required") if getattr(result_get, 'challenge_hhduc', None): handle_flicker_terminal() # else: mobile TAN/manual Smart-TAN/... is used while isinstance(result_get, NeedTANResponse): if result_get.decoupled: sleep(1.0) logger.info("poll for decoupled challenge") result_get = client.send_tan(result_get, None) else: tan = input('Please enter TAN:') logger.info("sending TAN") result_get = client.send_tan(result_get, tan)
Request for documentation
I'd suggest/request to update the documentation
Maybe update the "Full example" on the bottom of the page to show such polling instead of the "Please press enter after confirming the transa".. input?
Maybe provide two examples in "Sending the TAN", one for decoupled and one for standard?
I was looking for either of these.
Feedback to @jusernrone
Perhaps it would even make sense to allow send_tan to not require a tan (for these decoupled auth-methods) and add a spam-protection for looping calls?
While I get the reasoning, it feels odd to call a "send_tan" function anyway. I'd intuitively expect a (different) function like client.check_decoupled_auth(). Spam-protection I would as resposibility of the package-user, but it might be a good idea to add a (optional but default-on?) protection just to avoid that the package itself gets negative attention due to people using it inappropriately. Next-level of convenience could be a client.poll_until_decoupled_auth_given() that does the looping behind the scenes.
import logging
from datetime import date
import getpass
from fints.client import FinTS3PinTanClient
from fints.utils import minimal_interactive_cli_bootstrap
import time
from time import sleep
from fints.client import FinTS3PinTanClient, NeedTANResponse
print(" dieses Programm hat am 2025-08-03 funktioniert. man muss aber jedes Mal in der App entsprerren.")
# Enable debug logging for troubleshooting
logging.basicConfig(level=logging.DEBUG)
# DKB connection details
product_id = '6151256F3D4F9975B877BD4A2' # A generic product ID, or you can customize this
# Initialize the FinTS client
client = FinTS3PinTanClient(
bank_identifier= '12030000' ,
user_id= '1111_P',
pin= 'yourpin',
server='https://fints.dkb.de/fints',
product_id='6151256F3D4F9975B877BD4A2',
)
# Make sure this happens BEFORE `with client:`
client.fetch_tan_mechanisms()
mechs = client.get_tan_mechanisms()
client.set_tan_mechanism('940')
with client:
if isinstance(client.init_tan_response, NeedTANResponse):
if client.init_tan_response.decoupled:
print("Waiting for DKB App approval...")
# Poll for app approval
while isinstance(client.init_tan_response, NeedTANResponse):
sleep(1)
client.init_tan_response = client.send_tan(client.init_tan_response, None)
else:
tan = input("Enter TAN: ")
client.send_tan(client.init_tan_response, tan)
# After TAN is resolved:
time.sleep(8)
accounts = client.get_sepa_accounts()
print("\n Account Balances:")
for account in accounts:
try:
balance = client.get_balance(account)
currency = getattr(balance, 'currency', 'EUR')
print(f"- {account.iban} |>> you have so many coins : {balance.amount} {currency}")
except Exception as e:
print(f"- {account.iban} | Failed to fetch balance: {e}")
print("Accounts:", accounts)`
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
DEBUG:urllib3.connectionpool:https://fints.dkb.de:443 "POST /fints HTTP/1.1" 400 0
Traceback (most recent call last):
File "/Users/felix/repos/finanzguru-clone/.venv/lib/python3.14/site-packages/fints/client.py", line 1315, in _ensure_system_id
raise ValueError('Could not find system_id')
ValueError: Could not find system_id
During handling of the above exception, another exception occurred:
...
Claude says that the url should be https://banking-dkb.s-fints-pt-dkb.de/fints (is this correct?). However, there I get a 403 HTTP-Zugriff nicht gestattet.
The script from the post above gives me the same exceptions. Does anyone have a working DKB login?
EDIT: Interestingly enough with the product_id 6151256F3D4F9975B877BD4A2 the script from above works. I thought this was a made up id and I thought that the product_id is a secret.
I can reproduce your error when i use an invalid/random product_id. So i think that is your problem. https://fints.dkb.de/fints is right. (since Oct 2024)
If you plan to use FinTS you should get your own product_id via https://www.fints.org/de/hersteller/produktregistrierung (takes some weeks, 6 in my case).
Publicly known product_ids seem to be tolerated to a certain extent, but you shouldn't count on it.
Does anyone have a working DKB login?
I have DKB working using v5.0.0 (fab9877) and my own product_id.
Getting the ID was little effort, but I also hesitated at first.
I have DKB working using v5.0.0 (fab9877) and my own product_id.
Interesting, as mentioned above with the public product id the login works for me but with my one it doesn't. My ID works for other banks though. My guess is that my idea was not yet added to their accepted IDs. However, I am using the public one for now 👍🏻
Activity
mangoheini commentedon Feb 19, 2025
Just wanted to add, that the Saldo App does work great with my DKB bank account via chipTAN.
I'd also appreciate to have
TAN2GopushTAN added but please don't break chipTAN on that way. ;)edit: Apologies! I got the app-based methods mixed up.
mangoheini commentedon Feb 23, 2025
Apologies! I got the app-based methods mixed up. Corrected that.
nefarius2001 commentedon Apr 26, 2025
Hi,
could someone provide a minimal working example?
Here is what I have:
and I get this warning:
My App asks me for permission, I give that in mobile phone app and press Enter, but on the python side I get denied
_response in client.py:346][fints.client]
For some reason, the client.init_tan_response.decoupled is False - I have no idea where to look next. Do I have to enter the app-pin or something?
Jan-2k commentedon May 3, 2025
Hi,
I'm having the same issue. It looks like DKB expects a TAN although the decoupled TAN option is beeing used. I tried to send a 4 or 6 digit dummy TAN but still the same issue. Was somesone confronted with the same problem and found a solution?
thalwin commentedon May 30, 2025
HI,
i ran into the same issue using the testscript.py from https://python-fints.readthedocs.io/en/latest/trouble.html with DKB and App-TAN Authentication (940)
The DEBUG output showed it used "2" instead of "S" for the decoupled Authentication. So challenge.decoupled seems not to be set correct.
I got it running cutting back ask_for_tan in the testscript to
and further hardcoding challenge.decoupled to true in the client.send_tan method
So it seems to me the client does not set challenge.decoupled to true for the 940 method.
I will try to find a clean way patching the source ...
thalwin commentedon May 30, 2025
I traced the problem to the following lines in the dialog.py in init(), lines 87ff:
In my scenario DKB sends me the following Segments
What happens is that the code first creates a NeedTANResponse with decoupled=True (5th parameter:
resp.code == 3955) for the init_tan_response (this is what is needed), but overwrites it in the next loop (matching 0030) with decoupled=False (as resp.code != 3955).And indeed either limiting the if resp.code statement to
if resp.code == 3955or extending the 5th parameter of the NeedTANRespone toresp.code in ('0030', '3955')both solves the problem for me and the linked test-script above works nice.I can not really estimate which variant is right, as i have no experience with the FinTS yet. Personally i a actually working with extending
resp.code in ('0030', '3955')Also i would suggest a time.sleep(1) in the client.py after line 1370, so to not spam retrys to the server, and check "only" once in a sec, if the App-Auth worked ?
thalwin commentedon May 30, 2025
k... i just realized anyhow i debugged an old code.... the issue is already fixed on current master:
so no more issues for me...
edit: i just tried the script from @nefarius2001, it also works with the current github code. The latest "fints" Code (4.2.3 from Nov 2024) from PyPi however misses the fix for DKB.
nefarius2001 commentedon Jun 7, 2025
Thanks a lot @jusernrone !
I replaced the pip-installed 4.2.3 release with a submodule-clone of the repo using the current master (3d3644d).
It works!
May I ask a follow-up question:
Is there an resonable way to poll (like every second) if the App-Approval has been commited?
Asking the user to press enter when being done feels - clumsy
(see the line in my script "Please press enter after confirming the transaction in your app:")
thalwin commentedon Jun 8, 2025
It is documented for the send_tan() method:
So you can loop until it no more returns an instance of it:
Perhaps it would even make sense to allow
send_tanto not require a tan (for these decoupled auth-methods) and add a spam-protection for looping calls?nefarius2001 commentedon Jun 8, 2025
You are absolutely correct, thanks!
For other travellers: This is my code snippet called with client.init_tan_response and the result from client.get_transactions:
def handle_challenge( client, result_get ): if not isinstance(result_get, NeedTANResponse): logger.debug("No TAN is required") return result_get logger.info("TAN is required") if getattr(result_get, 'challenge_hhduc', None): handle_flicker_terminal() # else: mobile TAN/manual Smart-TAN/... is used while isinstance(result_get, NeedTANResponse): if result_get.decoupled: sleep(1.0) logger.info("poll for decoupled challenge") result_get = client.send_tan(result_get, None) else: tan = input('Please enter TAN:') logger.info("sending TAN") result_get = client.send_tan(result_get, tan)Request for documentation
I'd suggest/request to update the documentation
I was looking for either of these.
Feedback to @jusernrone
While I get the reasoning, it feels odd to call a "send_tan" function anyway. I'd intuitively expect a (different) function like client.check_decoupled_auth(). Spam-protection I would as resposibility of the package-user, but it might be a good idea to add a (optional but default-on?) protection just to avoid that the package itself gets negative attention due to people using it inappropriately. Next-level of convenience could be a client.poll_until_decoupled_auth_given() that does the looping behind the scenes.
NOYB4Europe commentedon Aug 3, 2025
felixschndr commentedon May 20, 2026
See edit below first
I am currently struggling with DKB login:
Gets me a
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> DEBUG:urllib3.connectionpool:https://fints.dkb.de:443 "POST /fints HTTP/1.1" 400 0 Traceback (most recent call last): File "/Users/felix/repos/finanzguru-clone/.venv/lib/python3.14/site-packages/fints/client.py", line 1315, in _ensure_system_id raise ValueError('Could not find system_id') ValueError: Could not find system_id During handling of the above exception, another exception occurred: ...Claude says that the url should be
https://banking-dkb.s-fints-pt-dkb.de/fints(is this correct?). However, there I get a 403HTTP-Zugriff nicht gestattet.The script from the post above gives me the same exceptions. Does anyone have a working DKB login?
EDIT: Interestingly enough with the product_id
6151256F3D4F9975B877BD4A2the script from above works. I thought this was a made up id and I thought that the product_id is a secret.thalwin commentedon May 21, 2026
I can reproduce your error when i use an invalid/random product_id. So i think that is your problem.
https://fints.dkb.de/fintsis right. (since Oct 2024)If you plan to use FinTS you should get your own product_id via
https://www.fints.org/de/hersteller/produktregistrierung(takes some weeks, 6 in my case).Publicly known product_ids seem to be tolerated to a certain extent, but you shouldn't count on it.
nefarius2001 commentedon May 24, 2026
Does anyone have a working DKB login?I have DKB working using v5.0.0 (fab9877) and my own product_id.
Getting the ID was little effort, but I also hesitated at first.
felixschndr commentedon May 25, 2026
Interesting, as mentioned above with the public product id the login works for me but with my one it doesn't. My ID works for other banks though. My guess is that my idea was not yet added to their accepted IDs. However, I am using the public one for now 👍🏻