yaybo
A terminal application for the Danish property registers. Look an address up, see what the land register holds against it, and keep the answers in a database you can query later.
uvx yaybo # the TUI, without installing it
uvx yaybo fetch "Prøvegade 1, 9999 Prøveby"
[!CAUTION] This is a hobby project. It is not built for production use, and nothing about it is supported.
It is not affiliated with, endorsed by, or connected to tinglysning.dk, Domstolsstyrelsen, MitID, NemLog-in, Boligsiden, Danmarks Statistik or Dataforsyningen. Those names appear here only to say where the data comes from.
Provided as-is, with no warranty of any kind. Use it at your own risk. The author accepts no liability for any loss, damage, or misuse arising from it, and none of it is financial, legal or property advice.
Everything is public data, from three sources that answer different questions:
| source | what it knows |
|---|---|
| tinglysning.dk | who owns a property, what is charged against it, every easement, every past transfer |
| Boligsiden | what it last sold for and per m², plus the BBR record — year built, rooms, walls, heating |
| Danmarks Statistik | what each kind of realkredit loan cost month by month, which is what lets a bare interest rate be read as an F3 or a fixed loan |
The register shows more of itself to someone who has proved who they are. Log in once with MitID and later runs quietly pick the session back up, adding each owner's date of birth, everyone named on every mortgage, and the chain of previous owners.
[!NOTE] This tells you who owns a property, not who lives there. Resident data (CPR/folkeregisteret) is not public in Denmark, with or without a login.
The TUI
Five screens, one database, and nothing that has to be typed twice.
Library — where it opens. Everything ever fetched, searchable offline, with
how stale each row is and its valuation, debt and loan-to-value at a glance.
enter opens a property, f re-fetches it, e exports the whole database.
Search — an address box that resolves against DAWA as you type, then asks the register which properties actually sit there. Two lists, on purpose:
- the addresses are DAWA's, and picking one costs nothing. Whole buildings
come first — asked about a house number DAWA answers with its flats, and the
register would be asked the same question about any of them.
↓moves from the box into the list,enteropens one,atakes its whole building. - the properties are the register's, and this is the list that matters: one
row for a rented block, a hundred-odd for a block of owner-occupied flats. It
is a multi-select —
spaceticks one,aticks all,nclears,ffetches the ticked ones, andctrl+Cstops a long run without losing what it already has.
While the address box has focus a letter is a letter, because addresses contain "30A". The status line says which keys are live at each step.
Property — one property, tab by tab, read back out of the database so it costs nothing and works offline:
- Oversigt — what it is, who owns it, what it is worth, what it owes
- Ejere · Hæftelser · Servitutter · Parter · Handler — the tables in full, with each charge's interest terms and the loan product they imply
- Forløb — sales, transfers, mortgages, easements and valuations merged onto one chronology. The register keeps these as four unrelated lists; putting them in date order is what makes a property's story legible.
- Kurve — price per square metre over time, plotted
- Bygning — the BBR record; Dokument — the signed attest itself
Queue — a whole street at a time. Type "Prøvegade, 9999", press Whole
street, and it queues every house number DAWA knows; or point it at a file with
one address per line. Progress bar, live per-row status, pause with space, and
whatever it has already fetched is already saved.
SQL — the accumulated database, queried directly, for the questions that only
exist once there is more than one property in it: price per m² by postcode,
owners of more than one flat, the most heavily mortgaged, buildings by age and
heating. Eight of those come ready to load and edit. Read-only, enforced by the
connection rather than by inspecting the SQL. ctrl+E exports any result.
Press ctrl+L anywhere to log in with MitID, or to log out.
Exporting
e on any screen, or --format on the command line. Three formats, and each
does the obvious thing with a set of related tables:
- DuckDB — one table each, the shape they were already in
- Excel — one sheet per table, header row frozen
- CSV — one file per table, in a folder named after the address
Column order follows the schema, so the same table exported twice has the same columns in the same places.
On the command line
yaybo fetch ADDRESS [--format duckdb,csv,xlsx] [--limit N] [--anonymous]
yaybo login --user YourMitIDUserID
yaybo status # is the session still good, and for how long
yaybo keepalive [MINUTES] # hold it open without another trip to the phone
yaybo backfill # re-derive the stored tables, fetching nothing
yaybo logout
fetch and the TUI share one pipeline, so neither can drift from the other.
Results accumulate in out/tinglysning.duckdb, replaced in place when an address
is looked up again — running the same address twice is a correction, not two
observations.
backfill rebuilds every table that is derived from a stored document — the
charges, the easements, everyone named on them, the historical owners — without
a login and without a single request to the register. Improving a reader makes
the existing rows out of date, not missing.
The tables
| table | one row per |
|---|---|
ejendomme |
property, with what it is worth, what it owes and what is left over |
ejere |
current owner |
haeftelser |
mortgage or charge, with its interest terms and estimated loan type |
servitutter |
easement, and what it is about |
dokument_parter |
person named on any document, with their role and date of birth or CVR |
underpant |
deed pledged on in its own right |
handelshistorik |
recorded sale, with the price per m² |
bygninger |
building in the BBR record |
adkomsthistorik |
past transfer, with what was paid |
adkomsthistorik_ejere |
person named in one of those transfers |
rentestatistik |
month of DST realkredit rates, kept so an estimate can be checked rather than taken on trust |
attester |
property's whole register document, as signed and as queryable JSON |
dokument_parter, adkomsthistorik and attester need a login. Everything else
does not.
[!WARNING] Some columns are worked out, not recorded, and they can be wrong.
samlet_gaeld_dkk,frivaerdi_dkkandbelaaningsgrad_pctare derived, and they run against the public valuation, which sits well below market. Treat the equity as a floor and the loan-to-value as a ceiling, never as a figure.
laantype_estimatis an estimate and not a record at all. The register gives an interest rate and never the product, so this is that rate matched against what each kind of loan actually cost in the months around it. The distance to the runner-up is inlaantype_afstandand the whole rate series is kept inrentestatistik, so an estimate can be argued with rather than taken on trust.
Installing
uv tool install yaybo # or: pip install yaybo
yaybo
uvx yaybo runs it without installing anything at all. Python 3.10 or newer.
To work on it, see CONTRIBUTING.md.
mitid-client — the login, on its own
The MitID half is a library of its own: mitid-client. It knows nothing about property - it is a Python stand-in for MitID's JavaScript core client, the NemLog-in broker that fronts the Danish public sector, a store for keeping a login's cookies between runs, and two ways of showing a login to whoever is doing it: a few lines on stderr, or a Textual screen.
from mitid.brokers import nemlogin
from mitid.ui.tui import MitIDLoginScreen
session = nemlogin.new_session()
result = await self.push_screen_wait(
MitIDLoginScreen(partial(nemlogin.log_in, session, START_URL))
)
Point it at any NemLog-in-protected URL and it comes back with the session cookie that URL was guarding. It installs as a dependency of this, so there is nothing to do about it; it is worth knowing about separately because a login is the reusable half, and property is not.
What you are taking on
[!WARNING] Everything this fetches is about real, named people — what they paid for their home, what they still owe on it, and, once logged in, when they were born. It is public record. That is not the same as it being yours to do whatever you like with.
- The moment you fetch it, you are the one holding it. In the EU that comes with obligations, and "it was already public" is not an answer for what you do next.
out/andexports/are git-ignored on purpose, and so is every data file anywhere in the tree. Keep it that way — a committed database is a published one.- Look up addresses you have a reason to look at.
[!IMPORTANT] The registers are public services, not scraping targets. There is a pause between requests and no attempt anywhere to go faster than a person clicking, and the queue is rate-limited for the same reason. Please leave it that way.
Logging in means logging in as you, to a government register, with MitID. See mitid-client for what that part carries with it.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file yaybo-0.2.1.tar.gz.
File metadata
- Download URL: yaybo-0.2.1.tar.gz
- Upload date:
- Size: 105.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.12.9 {"installer":{"name":"uv","version":"0.12.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e1be4fb4beceb164bf33cc4dd7ab906df22d846d8dd6c3b1b61aa9e649cc1028
|
|
| MD5 |
41f0b9b3ceb64cb7514d7d2f9c97b324
|
|
| BLAKE2b-256 |
124525699ccb9ca06af93cb2a49832347ae3369c387394b758f2ef3da57427ef
|
File details
Details for the file yaybo-0.2.1-py3-none-any.whl.
File metadata
- Download URL: yaybo-0.2.1-py3-none-any.whl
- Upload date:
- Size: 102.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.12.9 {"installer":{"name":"uv","version":"0.12.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5c7b07f16b18d4cc0f0d323d8a704eb4d992573bdbf65e6d0c57978cd0de655a
|
|
| MD5 |
97bbe7d35a9db04928349ca083fd6af9
|
|
| BLAKE2b-256 |
7aed20684c9215898edefecea7717c127cca8b333d230df3aa0c69348287c685
|