This is a library for the private API of the Trade Republic online brokerage. It is not affiliated with Trade Republic Bank GmbH.
Table of Contents
- Quickstart
- Usage
- Authentication
- Using pytr as a library
- Error Handling and Data Safety
- Development
- License
This is the right section for you if all you want to do is to "just run the thing". Whether you've never run a piece of code before, or are new to Python, these steps will make it the easiest for you to run pytr.
We strongly recommend that you use uv to run pytr. Since pytr is written
in the Python programming language, you usually need to make sure you have an installation of Python on your computer
before you can run any Python program. However, uv will take care of installing an appropriate Python version for
you if you don't already have one.
To install uv on OSX/Linux, run:
$ curl -LsSf https://astral.sh/uv/install.sh | shOn Windows, run:
> powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"Then, to run the latest released version of pytr:
$ uvx pytr@latestIf you want to use the cutting-edge version, use this command instead:
$ uvx --with git+https://github.com/pytr-org/pytr.git pytrusage: pytr [-h] [-V] [-v {warning,info,debug}] [--debug-logfile DEBUG_LOGFILE] [--debug-log-filter DEBUG_LOG_FILTER]
{help,login,dl_docs,portfolio,details,get_price_alarms,set_price_alarms,export_transactions,completion} ...
Use "pytr command_name --help" to get detailed help to a specific command
Commands:
{help,login,dl_docs,portfolio,details,get_price_alarms,set_price_alarms,export_transactions,completion}
Desired action to perform
help Print this help message
login Check if credentials file exists. If not create it and ask for input. Try to
login. Ask for device reset if needed
dl_docs Download all pdf documents from the timeline and sort them into folders. Also
export account transactions (account_transactions.csv) and JSON files with all
events (events_with_documents.json and other_events.json)
portfolio Show current portfolio
details Get details for an ISIN
get_price_alarms Get current price alarms
set_price_alarms Set new price alarms
export_transactions Create a CSV with the deposits and removals ready for importing into Portfolio
Performance
completion Print shell tab completion
Options:
-h, --help show this help message and exit
-V, --version Print version information and quit (default: False)
-v, --verbosity {warning,info,debug} Set verbosity level (default: info) (default: info)
--debug-logfile DEBUG_LOGFILE Dump debug logs to a file (default: None)
--debug-log-filter DEBUG_LOG_FILTER Filter debug log types (default: None)There are two authentication methods:
Web login is the newer method that uses the same login method as app.traderepublic.com,
meaning you receive a four-digit code in the TradeRepublic app or via SMS. This will keep you logged in your primary
device, but means that you may need to repeat entering a new four-digit code ever so often when runnnig pytr.
App login is the older method that uses the same login method as the TradeRepublic app. First you need to perform a device reset - a private key will be generated that pins your "device". The private key is saved to your keyfile. This procedure will log you out from your mobile device.
$ pytr login
$ # or
$ pytr login --phone_no +49123456789 --pin 1234If no arguments are supplied pytr will look for them in the file ~/.pytr/credentials (the first line must contain
the phone number, the second line the pin). If the file doesn't exist pytr will ask for for the phone number and pin.
Beyond the terminal interface, you can embed pytr into your own Python scripts. The recommended way is to use the TradeRepublic client, which provides a modern, high-level async API.
Below is an example demonstrating authentication, fetching portfolio, and handling potential API errors.
# client_example.py
import asyncio
from pathlib import Path
from pytr import TradeRepublic, FakeTradeRepublic
from pytr.errors import ApiShapeError
from pytr.models import Position, Transaction, CashBalance, Quote, Paginated
# ---------- Real client usage ----------
async def demo_real():
client = TradeRepublic(phone='+4912345678', pin='1234')
try:
auth = await client.authenticate()
if auth['requires_otp']:
code = input('Enter OTP: ')
await client.verify_otp(code)
positions: list[Position] = await client.positions()
print('Positions:', positions)
tx_page: Paginated[Transaction] = await client.transactions(limit=50)
print('Retrieved', len(tx_page.items), 'transactions')
cash: CashBalance = await client.cash()
print('Cash balance:', cash)
quotes: dict[str, Quote] = await client.quotes([p.isin for p in positions])
print('Quotes:', quotes)
# streaming timeline events (first page only)
async for ev in client.stream.timeline():
print('Timeline event:', ev)
break
except ApiShapeError as e:
print("The Trade Republic API has changed in an unexpected way.")
print("Please report this issue on GitHub.")
print("Sanitized error data:", e.data)
# ---------- Fake client usage for tests ----------
def demo_fake():
fake = FakeTradeRepublic(sample_dir=Path('tests'))
# run via asyncio.run in real code or pytest asyncio
positions = asyncio.run(fake.positions())
print('Fake positions:', positions)
tx_page = asyncio.run(fake.transactions(limit=5))
print('Fake transactions:', tx_page.items)
cash = asyncio.run(fake.cash())
print('Fake cash:', cash)
quotes = asyncio.run(fake.quotes([p.isin for p in positions]))
print('Fake quotes:', quotes)
if __name__ == "__main__":
asyncio.run(demo_real())This library interacts with an undocumented private API. This means the API can change without notice, which could cause unexpected errors. To handle this, pytr includes a robust mechanism to detect changes in the API response structure (known as "shape drift").
When the library receives data from the API that doesn't match the expected format, it will raise an ApiShapeError. This exception contains a sanitized version of the received data, making it safe to log for debugging purposes without exposing sensitive information like your account number or personal details.
This system, powered by the datason library, helps in two ways:
- It immediately alerts you that the API has changed.
- It provides the new data structure in a safe way, so the library can be updated.
Clone the repository:
$ git clone https://github.com/pytr-org/pytr.gitInstall dependencies (runtime + development extras):
# On zsh, quote the extras spec to avoid globbing:
$ pip install -e ".[dev]"Run the tests to ensure everything is set up correctly:
$ pytestThis project uses Ruff for code linting and auto-formatting, as well as Mypy for type checking.
You can auto-format the code with Ruff by running:
uv run ruff format # Format code
uv run ruff check --fix-only # Remove unneeded imports, order imports, etc.You can check the typing of the code with Mypy by running:
uv run mypy .Ruff and Mypy run as part of CI and your Pull Request cannot be merged unless it satisfies the linting, formatting checks and type checks.
- Create a pull request that bumps the version number in
pyproject.toml - After successfully merging the PR, create a new release via GitHub
and make use of the "Generate release notes" button. Tags are formatted as
vX.Y.Z. - The package will be published to PyPI from CI.
This readme contains a few automatically generated bits. To keep them up to date, simply run the following command:
$ uvx mksync@0.1.4 -i README.mdThis project is licensed under the MIT License. See the LICENSE file for details.