Google Sheets
Was du damit baust
Eine Google-Sheets-Tabelle, in der du links die Adresse einträgst und rechts der Bodenrichtwert steht. Typisch: eine Objektliste, daneben die Spalte „Bodenrichtwert €/m²".
Das funktioniert über IMPORTXML — eine Formel, die Google Sheets von Haus aus mitbringt. Kein Add-on, kein Apps Script, kein Code.
Was du vorher brauchst
- Ein Google-Konto mit Zugriff auf Google Sheets
- Einen bodenrichtwert.ai-Account (kostenlos starten)
- Einen API-Key aus deinem Dashboard — das ist ein Zugriffs-Schlüssel, der Sheets erlaubt, in deinem Namen abzufragen. Du findest ihn unter Dashboard → API-Keys. Leg ihn sicher ab, er ist nur einmal sichtbar.
Leg für Google Sheets am besten einen eigenen Key mit Ablaufdatum an und nicht den, den du schon woanders benutzt. Warum, steht unter Der Schlüssel steht in der Tabelle.
Die Formel
Tabelle vorbereiten
Leg die Tabelle so an:
- B1 — hier hinein kommt dein API-Key. Eine eigene Zelle, damit er nur an einer Stelle steht und du ihn später austauschen kannst, ohne jede Formel anzufassen.
- A2 und abwärts — die Adressen, je eine pro Zeile, mit Straße, Hausnummer und Ort. Zum Beispiel
Prenzlauer Allee 200, 10405 Berlin.
Formel in C2 einfügen
=IFERROR(IMPORTXML("https://api.bodenrichtwert.ai/api/bodenrichtwert?format=xml&nutzungsart=W&token=" & $B$1 & "&address=" & ENCODEURL(A2); "//bodenrichtwert[1]/brw_euro_pro_m2"); "kein Wert")
In der Zelle steht danach nur die Zahl, zum Beispiel 5000.
; durch ,.Nach unten ziehen
Zelle C2 anklicken, unten rechts am kleinen Quadrat anfassen und über alle Zeilen mit Adressen ziehen. Fertig.
Was die Formel macht
| Baustein | Wozu |
|---|---|
format=xml | Liefert die Antwort als XML statt als JSON — nur das versteht IMPORTXML. |
nutzungsart=W | Beschränkt auf Wohnbauflächen — sonst kämen auch Gewerbe- und Mischflächen zurück. Für Gewerbe nimmst du nutzungsart=G. |
ENCODEURL(A2) | Übersetzt Leerzeichen und Umlaute in ein Format, das in eine Web-Adresse passt. Ohne das schlagen alle Adressen mit „ß" oder Umlaut fehl. |
//bodenrichtwert[1]/… | Nimmt den ersten Eintrag. Entscheidend für die Zeilenausrichtung — siehe Kasten unten. |
brw_euro_pro_m2 | Der Bodenrichtwert in Euro pro Quadratmeter. |
IFERROR(…; "kein Wert") | Schreibt „kein Wert" in die Zelle, statt eine Fehlermeldung anzuzeigen, wenn es für die Adresse nichts gibt. |
[1] nicht weg. An einer Adresse können mehrere Bodenrichtwertzonen derselben Nutzungsart aneinandergrenzen — die Prenzlauer Allee 200 in Berlin liefert zum Beispiel zwei Wohn-Zonen mit 5.000 und 5.500 €/m². Ohne [1] schreibt Sheets beide Werte untereinander und überschreibt damit die Zeile darunter, also die nächste Adresse deiner Liste. Mit [1] bekommst du immer genau eine Zelle.Wenn du wissen willst, ob es an einer Adresse mehrere Zonen gibt, zieh sie dir einmalig in einer freien Zelle mit //brw_euro_pro_m2 (ohne [1]) — dann siehst du alle.Weitere Spalten
Die Antwort enthält mehr als nur den Preis. Für zusätzliche Spalten tauschst du den letzten Teil der Formel aus:
| Was du willst | Statt //bodenrichtwert[1]/brw_euro_pro_m2 |
|---|---|
| Stichtag des Werts | //bodenrichtwert[1]/stichtag |
| Gemeinde | //bodenrichtwert[1]/gemeinde |
| Zuständiger Gutachterausschuss | //bodenrichtwert[1]/gutachterausschuss |
| Gefundene Adresse (zur Kontrolle) | //address_resolved |
| Quellenangabe | //attribution/text |
Die letzten beiden stehen einmal pro Antwort und brauchen deshalb kein [1].
Die Bezeichnungen sind dieselben wie in der REST-API — was dort als Feld dokumentiert ist, funktioniert hier als Formel-Ausdruck.
Jeder Refresh kostet einen Abruf
Das ist die wichtigste Eigenschaft dieser Lösung, und sie überrascht fast jeden:
Google Sheets aktualisiert IMPORTXML-Formeln von selbst. Etwa stündlich, außerdem beim Öffnen der Tabelle und bei vielen Bearbeitungen. Jede dieser Aktualisierungen ist ein vollwertiger Abruf und wird von deinem Monatskontingent abgezogen — auch wenn sich am Ergebnis nichts geändert hat.
Eine Beispielrechnung mit dem Starter-Plan (50 Abfragen im Monat):
| Situation | Verbrauch |
|---|---|
| 20 Adressen, einmal eingefügt | 20 Abrufe |
| Tabelle am selben Tag dreimal geöffnet | + 60 Abrufe |
| Summe | 80 — Kontingent an einem Tag aufgebraucht |
Die Lösung: Werte einfrieren
Sobald die Spalte gefüllt ist, machst du aus den Formeln feste Zahlen. Dann steht der Wert dauerhaft in der Tabelle und es wird nie wieder nachgeladen:
- Die fertige Spalte markieren und kopieren (
Strg/Cmd+C) - Bearbeiten → Inhalte einfügen → Nur Werte einfügen (
Strg/Cmd+Shift+V)
Das ist bei dieser Lösung nicht die Notlösung, sondern der Normalfall: Bodenrichtwerte ändern sich zum Stichtag, also in der Regel einmal jährlich — eine stündliche Aktualisierung bringt dir nichts und kostet dich dein Kontingent.
Dein aktueller Verbrauch steht jederzeit im Dashboard.
Der Schlüssel steht in der Tabelle
Der API-Key ist Teil der Formel. Jeder, der die Tabelle öffnen darf, kann ihn auslesen — auch mit reiner Leseberechtigung, denn ein Klick auf die Zelle zeigt die Formel. Wenn du die Tabelle teilst, teilst du deinen Schlüssel mit.
Deshalb:
- Für Google Sheets einen eigenen Key anlegen, nicht den aus anderen Integrationen mitbenutzen
- Beim Anlegen ein Ablaufdatum setzen
- Vor dem Teilen der Tabelle die Werte einfrieren und die Key-Zelle leeren
- Bei Verdacht: Key im Dashboard widerrufen und neu anlegen — die Formeln funktionieren nach dem Austausch in B1 sofort weiter
?token= existiert genau für Werkzeuge wie Sheets, die technisch keine Header senden können. Überall sonst — eigene Skripte, Server, Automatisierungen — nimm den Authorization-Header, siehe Authentifizierung.Testen
Ob dein Key funktioniert, prüfst du am schnellsten außerhalb der Tabelle: URL zusammenbauen, Key einsetzen und im Browser öffnen.
https://api.bodenrichtwert.ai/api/bodenrichtwert?format=xml&nutzungsart=W&address=Prenzlauer%20Allee%20200,%2010405%20Berlin&token=DEIN_API_KEY
Es sollte etwa so aussehen (gekürzt):
<?xml version="1.0" encoding="UTF-8"?>
<response>
<address_input>Prenzlauer Allee 200, 10405 Berlin</address_input>
<address_resolved>Prenzlauer Allee 200, 10405 Berlin - Prenzlauer Berg</address_resolved>
<bodenrichtwerte>
<bodenrichtwert>
<nutzungsart>Wohnbaufläche</nutzungsart>
<code>W</code>
<brw_euro_pro_m2>5000</brw_euro_pro_m2>
<stichtag>2026-01-01</stichtag>
<gemeinde>Berlin</gemeinde>
</bodenrichtwert>
</bodenrichtwerte>
<attribution>
<text>© Daten der Gutachterausschüsse für Grundstückswerte 2026, dl-de/by-2-0</text>
</attribution>
</response>
Diese Adresse ist bewusst gewählt: sie liefert zwei Wohn-Zonen und zeigt damit direkt, warum die [1] in der Formel steht.
Achtung: Dieser Test kostet ebenfalls einen Abruf.
Wenn es nicht klappt
In der Zelle steht bei jedem Problem #N/A — die Formel kann Fehlermeldungen nicht anzeigen. Den Grund holst du dir mit einer Diagnose-Formel in einer freien Zelle: dieselbe URL, aber //message als Ausdruck.
=IMPORTXML("https://api.bodenrichtwert.ai/api/bodenrichtwert?format=xml&token=" & $B$1 & "&address=" & ENCODEURL(A2); "//message")
Was dort stehen kann:
- „Token ist ungültig oder abgelaufen" — Key falsch kopiert oder abgelaufen. Im Dashboard neu anlegen und B1 aktualisieren.
- „Adresse nicht gefunden" — Adresse unvollständig. Straße, Hausnummer und Ort angeben, Postleitzahl hilft zusätzlich.
- „… stellt aktuell keine Bodenrichtwerte bereit" — die Adresse liegt in Schleswig-Holstein, Sachsen oder Bayern. Für diese drei Bundesländer stehen keine Daten zur Verfügung.
- „Dein Monats-Kontingent ist aufgebraucht" — siehe Jeder Refresh kostet einen Abruf. Werte einfrieren und gegebenenfalls upgraden.
Weitere Symptome:
- Alle Zeilen zeigen
#N/A, obwohl der Browser-Test klappt — meist die Argument-Trennung: Semikolon gegen Komma tauschen (oder umgekehrt), je nach Spracheinstellung der Tabelle. - Werte landen in den falschen Zeilen — die
[1]fehlt im Ausdruck. An Adressen mit mehreren Zonen schreibt Sheets sonst alle Werte untereinander. - Eine Adresse liefert „kein Wert", obwohl es dort Grundstücke gibt — oft passt nur die Nutzungsart nicht. Das Kölner Domkloster etwa liegt in einer Mischbaufläche, nicht in einer Wohnbaufläche: mit
nutzungsart=Wkommt nichts, mitnutzungsart=Mschon. Lass den Filter einmal ganz weg, um zu sehen, was es an der Adresse gibt. - Umlaut-Adressen schlagen fehl —
ENCODEURL(A2)fehlt oder die Adresse steht direkt in der URL statt in einer Zellreferenz.
Wann Sheets das falsche Werkzeug ist
Diese Lösung ist für überschaubare Listen gedacht, die du einmal befüllst. Wenn du regelmäßig größere Mengen verarbeitest oder die Werte in ein anderes System schreiben willst, passt eines der anderen Rezepte besser:
- n8n oder Zapier / Make — schreiben die Werte automatisiert in deine Tabelle oder dein CRM
- Python / pandas — für Batch-Läufe über größere Adresslisten