Automatically reserve study spaces and library seats on anny.eu — the booking platform used by university libraries across Germany, including the Karlsruhe Institute of Technology (KIT) and the Technical University of Munich (TUM).
The script logs in via SAML Single Sign-On (SSO), waits until midnight when new slots open, and instantly books your preferred time slot — fully automated.
- Auto-discovery — Automatically detects your library's resource and service IDs after login; no manual API research needed
- Pluggable SSO — Built-in providers for KIT (Karlsruhe Institute of Technology) and TUM (Technical University of Munich); easily extendable for other universities
- Smart scheduling — Waits until midnight when new booking slots open, or runs immediately for testing
- Configurable time slots — Set your preferred booking times in order of priority
- Resource priority — Define preferred desk or room IDs; falls back to any available resource
- Environment-based config — All settings via
.envfile or GitHub Secrets; no code changes required - Flexible execution — Runs via GitHub Actions + cron-job.org (no server needed), or as a self-hosted Linux cron job
| University | SSO Provider | Status |
|---|---|---|
| Karlsruhe Institute of Technology (KIT) | kit |
✅ Supported |
| Technical University of Munich (TUM) | tum |
✅ Supported |
| Other Anny-based libraries | Custom provider | See Adding a New SSO Provider |
Choose your setup path and jump to the relevant section:
- Option A: GitHub Actions + cron-job.org — No server needed. Fork the repo, add secrets, done.
- Option B: Self-hosted Linux Cron — Clone, configure a
.envfile, and run on your own server.
Two options are supported: GitHub Actions (no server needed) or a self-hosted Linux cron job (for users who run their own server).
GitHub Actions on: schedule has two issues:
- Queue delays — Workflows can be delayed by minutes, missing the booking window
- UTC only — No timezone support, requiring manual DST adjustments
cron-job.org provides precise, timezone-aware scheduling with no delays.
Click the Fork button on the GitHub repository page to create your own copy. The GitHub Actions workflow is already included.
⚠️ Security: Forks of public repositories are public by default. Since your credentials are stored as GitHub Secrets (not in code), they are safe — but it is still recommended to set your fork to private: go to your fork's Settings > Danger Zone > Change visibility. Also remember: Never commit or push a.envfile to any GitHub repository.
In your forked repository: Settings > Secrets and variables > Actions
Add the following repository secrets:
| Secret | Value |
|---|---|
USERNAME |
Your university username |
PASSWORD |
Your university password |
TIMEZONE |
Your timezone (e.g. Europe/Berlin) |
BOOKING_TIMES |
Comma-separated time slots (e.g. 14:00:00-19:00:00, 09:00:00-13:00:00) |
SSO_PROVIDER |
kit or tum |
RESOURCE_IDS |
Preferred resource IDs (optional) |
USE_ANY_RESOURCE_ID |
True or False |
- Go to GitHub Settings > Developer settings > Personal access tokens
- Generate a token with
reposcope (or fine-grained with Actions read/write) - Copy the token
Create a new cron job with these settings:
| Setting | Value |
|---|---|
| URL | https://api.github.com/repos/YOUR_USERNAME/anny-booking-automation/actions/workflows/schedule.yml/dispatches |
| Schedule | 58 23 * * * (23:58 daily) |
| Timezone | Europe/Berlin (or your timezone) |
| Request method | POST |
Headers:
Authorization: Bearer YOUR_GITHUB_TOKEN
Content-Type: application/json
Accept: application/vnd.github.v3+json
Request body:
{"ref": "main"}- cron-job.org triggers the workflow at 23:58
- The script logs in and establishes a session
- It waits until 00:00 when new slots become available
- Instantly books the first available slot from your priority list
If you have a Linux server (Raspberry Pi, VPS, etc.) you can run the script directly without GitHub Actions.
- Clone and install the project on your server:
git clone https://github.com/wiestju/anny-booking-automation.git
cd anny-booking-automation
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt- Create your
.envfile by copying the example template and filling in your values:
cp .env.example .env| Variable | Required | Default | Example | Description |
|---|---|---|---|---|
USERNAME |
Yes | — | student123 |
Your university login username |
PASSWORD |
Yes | — | secret |
Your university login password |
SSO_PROVIDER |
Yes | — | kit |
SSO provider (kit or tum) |
RESOURCE_URL_PATH |
No | Auto-discovered | /resources/1-lehrbuchsammlung-eg-und-1-og/children |
API path for your library's rooms. Detected automatically if not set. |
SERVICE_ID |
No | Auto-discovered | 449 |
Booking service ID for your library. Detected automatically if not set. |
TIMEZONE |
No | Europe/Berlin |
Europe/Berlin |
Timezone for the midnight wait |
BOOKING_TIMES |
No | 14:00:00-19:00:00, 09:00:00-13:00:00, 20:00:00-23:45:00 |
14:00:00-19:00:00, 09:00:00-13:00:00 |
Desired time slots in priority order (hh:mm:ss-hh:mm:ss, comma-separated) |
RESOURCE_IDS |
No | — | 5957, 5958 |
Preferred desk or room IDs tried first (comma-separated) |
USE_ANY_RESOURCE_ID |
No | False |
True |
If True, falls back to any available resource after trying RESOURCE_IDS |
Note:
RESOURCE_URL_PATHandSERVICE_IDare automatically discovered from the Anny API after login. You only need to set them manually if auto-discovery picks the wrong resource (e.g. if your account has access to multiple libraries).Note: At least one of
RESOURCE_IDSorUSE_ANY_RESOURCE_ID=Truemust be set, otherwise no resource will be booked.
See .env.example for a ready-to-copy template including examples for KIT and TUM.
- Make the run script executable:
chmod +x scripts/run.sh- Add a cron entry that fires at 23:58 every night:
crontab -eAdd this line (replace /path/to with the actual path):
58 23 * * * /path/to/anny-booking-automation/scripts/run.sh >> /path/to/anny-booking-automation/logs/cron.log 2>&1
Tip: Create the logs directory first:
mkdir -p /path/to/anny-booking-automation/logs
The script activates the virtual environment and runs main.py automatically. Logs are written to logs/cron.log.
- The system cron fires
scripts/run.shat 23:58 in your server's local time - The script logs in and establishes a session
- It waits until 00:00 when new slots become available
- Instantly books the first available slot from your priority list
Timezone note: The script uses the
TIMEZONEenv var to determine when midnight occurs. Make sure your server's local time matches your target timezone, or setTIMEZONEexplicitly in your.env.
anny-booking-automation/
├── main.py # Entry point
├── .env.example # Example environment configuration
├── scripts/
│ └── run.sh # Wrapper script for self-hosted Linux cron
├── config/
│ └── constants.py # Loads settings from environment / .env
├── auth/
│ ├── session.py # Login session handling and customer account discovery
│ └── providers/ # SSO provider implementations
│ ├── base.py # Abstract base class
│ ├── kit.py # Karlsruhe Institute of Technology (KIT)
│ └── tum.py # Technical University of Munich (TUM)
├── booking/
│ └── client.py # Booking API client and resource auto-discovery
└── utils/
└── helpers.py # Utility functions
To add support for another university that uses Anny for library bookings, create auth/providers/youruni.py:
from auth.providers.base import SSOProvider
class YourUniProvider(SSOProvider):
name = "Your University Name"
domain = "youruni.edu"
available_days_ahead = 3 # How many days ahead bookings open
def authenticate(self) -> str:
# Implement the university's SAML authentication flow
# Use self.session, self.redirect_response, self.username, self.password
# Return the HTML page containing the SAMLResponse form field
passRegister it in auth/providers/__init__.py:
from auth.providers.youruni import YourUniProvider
PROVIDERS = {
"kit": KITProvider,
"tum": TUMProvider,
"youruni": YourUniProvider,
}Then set SSO_PROVIDER="youruni" in your .env file.
MIT