Tutorial: geoAPI in deine eigene Website einbauen
Diese Anleitung führt dich Schritt für Schritt zum ersten funktionierenden Eingabeformular mit Ortssuche. Kein Vorwissen über APIs nötig — wenn du schon mal eine HTML-Datei auf deinen Webspace hochgeladen hast, reicht das.
Was ist die geoAPI eigentlich?
Die geoAPI ist ein kostenloser Online-Dienst, an den du eine Anfrage schicken kannst — z. B. „suche Orte, deren Name mit ‚Münch' beginnt" — und der dir dann eine Antwort mit den passenden Treffern zurückgibt. Diese Antworten kannst du in deine eigene Webseite einbauen, ohne selbst eine Datenbank mit Millionen Orten betreiben zu müssen.
Beispiele, was du damit machen kannst:
- Ein Eingabefeld, das während des Tippens passende Orte vorschlägt (Autosuggest).
- Aus Koordinaten (Breite/Länge) den Stadtnamen und die Zeitzone ermitteln.
- Geburtsorte fürs Horoskop, Reiseziele für Buchungen, Standorte für Wettervorhersagen.
Was du brauchst
- Webspace mit PHP-Unterstützung — z. B. dein normales Webhosting bei einem Anbieter wie Infomaniak, Strato, IONOS, All-Inkl … oder lokal auf deinem Rechner mit MAMP/XAMPP. Reine HTML-Seiten ohne PHP reichen für Variante A schon.
- Ein FTP-Programm, um Dateien auf den Webspace zu legen — Cyberduck, FileZilla, Transmit. Manche Hoster haben auch einen Datei-Manager im Browser.
- Ein Texteditor, mit dem du HTML/PHP-Dateien öffnen und bearbeiten kannst — Notepad++ (Windows), TextMate/BBEdit (Mac), VS Code (alle Plattformen). Word funktioniert nicht, weil das Formatierungen einbaut.
Zwei Wege zum Ziel — was wann?
| Variante A: Browser-Widget | Variante B: PHP-Client | |
|---|---|---|
| Wann? | Du willst ein Eingabefeld mit Live-Vorschlägen, während der Nutzer tippt. | Du musst auf dem Server selbst etwas ausrechnen — z. B. wenn der Nutzer nur Koordinaten kennt, aber keine Stadt. |
| Aufwand | 2 Zeilen HTML | 1 Datei hochladen, 5 Zeilen PHP |
| JavaScript nötig? | Ja (übernimmt das Widget). | Nein. |
Du kannst beide kombinieren — siehe Schritt 5 unten.
Variante A: Browser-Widget einbauen
-
Eine HTML-Datei anlegen
Öffne deinen Texteditor und erstelle eine neue Datei mit folgendem Inhalt:
<!DOCTYPE html> <html lang="de"> <head> <meta charset="utf-8"> <title>Mein erstes Ort-Formular</title> </head> <body> <h1>Wo wurdest du geboren?</h1> <form method="post" action="speichern.php"> <label>Ort: <input type="text" name="ort" data-geoapi-place placeholder="z. B. München, Wien, Zürich"> </label> <button type="submit">Speichern</button> </form> <script src="https://geoapi.world/dist/geoapi-widget.js"></script> </body> </html>Speichere sie unter dem Namen ort.html.
-
Auf den Webspace hochladen
Verbinde dich mit deinem FTP-Programm zum Webspace und lade ort.html in das Hauptverzeichnis deiner Website hoch (oft heißt das
public_html,htdocsoderwww).Lokales Testen geht auch — falls du XAMPP/MAMP installiert hast, leg die Datei einfach inhtdocsbzw.htdocs/dein-projekt/und ruf sie überhttp://localhost/ort.htmlauf. -
Im Browser öffnen und ausprobieren
Rufe die Datei in deinem Browser auf — z. B.
https://deine-domain.de/ort.html. Du solltest jetzt ein Eingabefeld sehen. Tippe dort „Münch" ein. Während du tippst, erscheint eine Vorschlagsliste mit Treffern: Munich, Münchberg, Münchenstein …Es funktioniert? Gratuliere! Du hast gerade eine echte API in deine Website eingebunden. Das Widget hat sich aus dem Internet geladen, das Eingabefeld erkannt und sich um die ganze Kommunikation mit dem geoAPI-Server gekümmert.Wenn du auf einen Vorschlag klickst, wird der Ortsname ins Eingabefeld übernommen und im Hintergrund werden zusätzlich zwei „unsichtbare" Felder gefüllt: die geoNames-ID und die Zeitzone des Ortes.
-
Was passiert beim Klick auf „Speichern"?
Im Moment hast du noch kein Server-Skript, das die Eingabe verarbeitet — die Form schickt an
speichern.php, die es noch nicht gibt. Im nächsten Abschnitt bauen wir das.Falls du nur sehen willst, was am Server angekommen wäre, ohne ein Skript zu schreiben: rufe stattdessen unsere Live-Demo auf — dort wird genau das in Echtzeit angezeigt.
Schritt 5: Server-Skript schreiben (PHP)
-
Datei
speichern.phpanlegenIm selben Verzeichnis wie ort.html:
<?php // Werte aus dem Formular einlesen, mit Standardwerten falls leer $ort = trim($_POST["ort"] ?? ""); $geonameid = (int) ($_POST["ort_geonameid"] ?? 0); $timezone = trim($_POST["ort_timezone"] ?? ""); // Plausibilitätscheck: hat der Nutzer einen Vorschlag aus der Liste gewählt? if ($geonameid === 0) { die("Bitte wähle einen Vorschlag aus der Liste, statt nur zu tippen."); } ?> <!DOCTYPE html> <html lang="de"><head><meta charset="utf-8"><title>Gespeichert</title></head> <body> <h1>Danke!</h1> <p>Du hast gewählt: <strong><?= htmlspecialchars($ort) ?></strong></p> <p>geoNames-ID: <?= $geonameid ?></p> <p>Zeitzone: <?= htmlspecialchars($timezone) ?></p> <p>In einer echten Anwendung würdest du diese Werte jetzt in eine Datenbank schreiben oder weiterverarbeiten.</p> </body></html>Hochladen wie beim ersten Mal — auch in das Hauptverzeichnis.
-
Test
Rufe wieder
https://deine-domain.de/ort.htmlauf, tippe „Münch", wähle „Munich" aus der Liste und klicke „Speichern". Du solltest jetzt eine Bestätigungsseite mit den ausgewählten Daten sehen.Was hast du gerade gebaut? Ein vollständiges Web-Formular mit Live-Suche, Form-Validierung und Server-Verarbeitung. Das ist die Basis für jeden Anwendungsfall, bei dem ein Nutzer einen Ort eingeben soll.
Variante B: PHP-Client für Server-Aufrufe
Manchmal willst du auf dem Server selbst die geoAPI fragen — ohne Browser, ohne JavaScript. Beispiele:
- Du hast Koordinaten aus einem GPS-Track und brauchst dazu die Stadt + Zeitzone.
- Du verarbeitest CSV-Imports und willst Ortsnamen automatisch validieren.
- Du baust einen Cron-Job, der täglich Daten anreichert.
-
Den PHP-Client herunterladen
Lade die Datei von dieser Adresse:
https://geoapi.world/download.php?file=client
Du bekommst eine Datei GeoApiClient.php. Lade sie in dein Projekt-Verzeichnis hoch.
-
Eigene PHP-Datei schreiben, die den Client benutzt
Erstelle test-client.php im selben Verzeichnis:
<?php require __DIR__ . "/GeoApiClient.php"; $api = new GeoApiClient(); // Beispiel 1: Suche nach Namen echo "<h2>Suche nach 'Münch'</h2><ul>"; foreach ($api->search("Münch", limit: 5) as $ort) { echo "<li>" . htmlspecialchars($ort["name"]) . " (" . $ort["country_code"] . "), " . htmlspecialchars($ort["timezone"]) . "</li>"; } echo "</ul>"; // Beispiel 2: Reverse-Geocoding (Koordinaten → Stadt) $ort = $api->lookupCity(48.137, 11.575); echo "<h2>Stadt zu 48.137 / 11.575</h2>"; echo "<p>" . htmlspecialchars($ort["name"]) . " in der Zeitzone " . htmlspecialchars($ort["timezone"]) . " (Entfernung: " . $ort["distance_km"] . " km)</p>"; -
Im Browser aufrufen
Rufe
https://deine-domain.de/test-client.phpauf. Du siehst eine Liste von Münch-Treffern und die zur Koordinate passende Stadt mit Zeitzone.Sobald das hier funktioniert, kannst du den Code in deine eigenen Anwendungen einbauen — z. B. in das speichern.php aus Variante A, um Eingaben serverseitig nochmal nachzuprüfen.
Schritt 6: Beide Varianten kombinieren (empfohlen)
In der Praxis ist es sinnvoll, das Browser-Widget mit einer Server-Validierung zu ergänzen. Falls jemand JavaScript ausgeschaltet hat oder den Hidden-Werten nicht traut, springt der Server-Code ein:
<?php
require __DIR__ . "/GeoApiClient.php";
$ort = trim($_POST["ort"] ?? "");
$geonameid = (int) ($_POST["ort_geonameid"] ?? 0);
if ($geonameid > 0) {
// Browser-Widget hat einen Vorschlag gewählt — alle Daten sind da.
$name = $ort;
$timezone = $_POST["ort_timezone"] ?? "";
} else {
// Kein Widget-Vorschlag (JS aus, getippt ohne auszuwählen, …):
// Server fragt selbst die geoAPI mit dem getippten Text.
$api = new GeoApiClient();
$first = $api->search($ort, 1)[0] ?? null;
if ($first === null) {
die("Kein Ort gefunden für: " . htmlspecialchars($ort));
}
$name = $first["name"];
$geonameid = $first["geonameid"];
$timezone = $first["timezone"];
}
echo "Gespeichert: $name (ID $geonameid, Zeitzone $timezone)";
Häufige Probleme und Lösungen
Es passiert nichts, wenn ich tippe — keine Vorschläge.
Öffne die Browser-Konsole (Rechtsklick → „Untersuchen" → Tab „Konsole" oder F12). Wenn dort eine Fehlermeldung in Rot steht, lies sie:
net::ERR_NAME_NOT_RESOLVED: keine Internetverbindung oder Tippfehler in der URLgeoapi.world.CORS-Fehler: das sollte nicht passieren — die geoAPI hat CORS für alle Domains offen. Falls doch: lade die Seite über HTTPS, nichtfile://(also nicht durch Doppelklick im Datei-Explorer öffnen).- Kein Fehler, aber trotzdem nichts? Prüf, ob das
data-geoapi-place-Attribut wirklich auf dem<input>steht.
Im Server-PHP kommen die Hidden-Felder leer an.
Drei mögliche Gründe:
- Der Nutzer hat keinen Vorschlag ausgewählt, sondern nur getippt. Hidden-Felder werden nur beim Klick/Enter gefüllt.
- Das Form hat
method="get"stattmethod="post"— dann musst du$_GETstatt$_POSTauslesen. - Die Hidden-Felder haben einen anderen Namen, als du im PHP erwartest. Standard ist
<name>_geonameidund<name>_timezone. Wenn dein Inputname="ort"heißt, also$_POST["ort_geonameid"].
Funktioniert das auch ohne PHP, nur mit reinem HTML?
Variante A (Browser-Widget) ja — eine reine .html-Datei reicht, solange du das Formular nicht weiterverarbeitest, sondern z. B. die Werte mit JavaScript an einen anderen Dienst schickst (z. B. Google Forms, Make/Zapier, eigener Webhook).
Variante B (PHP-Client) braucht zwingend einen PHP-fähigen Server.
Kann ich das Aussehen der Vorschlagsliste ändern?
Ja, alles über CSS-Variablen — einfach in den <head>-Bereich deiner Seite:
<style>
:root {
--geoapi-bg: #fff; /* Hintergrund der Liste */
--geoapi-fg: #222; /* Schriftfarbe */
--geoapi-muted: #666; /* Untertitel/Hint-Farbe */
--geoapi-border: #ccc; /* Außenrahmen */
--geoapi-border-light: #eee; /* Trennlinien */
--geoapi-active-bg: #fff3b0; /* Markierung beim Hovern */
--geoapi-radius: 4px;
--geoapi-shadow: 0 4px 12px rgba(0,0,0,0.08);
--geoapi-max-height: 260px;
--geoapi-padding-x: 0.7rem;
--geoapi-padding-y: 0.4rem;
--geoapi-font-size: inherit;
--geoapi-z-index: 1000;
}
</style>
Wenn das nicht reicht: direkt die Klassen .geoapi-suggest-list und .geoapi-suggest-list li überschreiben. Live ausprobieren auf demo.php#anpassen (Block D).
Wie ändere ich, was in der Vorschlagsliste angezeigt wird? Ich will z. B. nicht „Munich (DE)" sondern nur „Munich".
Mit den Attributen data-geoapi-format-list und data-geoapi-format-input. Platzhalter sind in geschweiften Klammern:
<!-- Liste: nur Name + Region als Untertitel; Eingabefeld: nur Name -->
<input type="text" name="ort" data-geoapi-place
data-geoapi-format-list="{name}<small>{admin1_code} · {timezone}</small>"
data-geoapi-format-input="{name}">
Verfügbare Platzhalter: {name}, {asciiname}, {country_code}, {admin1_code}, {feature_code}, {population}, {timezone}, {lat}, {lon}, {geonameid}. HTML im Format-String ist erlaubt; die Daten selbst werden automatisch escapet (kein XSS-Risiko).
Wie kann ich die Daten des ausgewählten Ortes auf meiner Seite weiterverwenden — z. B. Land, Zeitzone, Einwohner woanders anzeigen?
Variante 1 — Auto-Fill (deklarativ, ohne JavaScript): setze data-geoapi-fill="key" auf beliebige HTML-Elemente. Inputs/Textareas bekommen den Wert in value, andere Elemente als Textinhalt.
<input type="text" name="ort" data-geoapi-place>
<p>Land: <span data-geoapi-fill="country_code"></span></p>
<p>Zeitzone: <span data-geoapi-fill="timezone"></span></p>
<p>Einwohner: <span data-geoapi-fill="population"></span></p>
<p>Koordinaten: <span data-geoapi-fill="lat"></span>,
<span data-geoapi-fill="lon"></span></p>
Variante 2 — JavaScript-Event: wenn du eigene Logik anstoßen willst (Karte zentrieren, Berechnung starten, eigene Felder befüllen):
document.querySelector("[data-geoapi-place]")
.addEventListener("geoapi:select", (e) => {
const ort = e.detail;
// ort hat alle Felder: name, country_code, timezone, lat, lon, population, …
console.log("Gewählt:", ort.name);
document.getElementById("meine-anzeige").textContent = ort.name + " in " + ort.timezone;
// map.setView([ort.lat, ort.lon], 13);
});
Beide Varianten kombinierbar. Live ausprobieren auf demo.php#anpassen (Block B).
Wie sehe ich, was die Hidden-Felder gerade enthalten — ohne in den Browser-Inspektor zu schauen?
Setze data-geoapi-debug auf das Eingabefeld. Das Widget zeigt dann eine kleine Box unter dem Input mit allen aktuellen Werten — sehr praktisch beim Entwickeln. In der produktiven Version das Attribut wieder weglassen.
<input type="text" name="ort" data-geoapi-place data-geoapi-debug>
Live: demo.php#anpassen (Block C).
Wie viele Anfragen kann ich machen? Kostet das etwas?
Aktuell gibt es kein hartes Limit und der Dienst ist kostenfrei. Bitte trotzdem fair sein:
- Beim Browser-Widget ist das schon eingebaut — eine 200-ms-Pause zwischen Tastendrücken bremst die Anfragen.
- Beim Server-Aufrufen: cache deine Ergebnisse, wenn du dieselben Koordinaten/Suchen mehrfach abfragst. Der PHP-Client unterstützt das eingebaut über den
cacheDir/cacheTtlSeconds-Parameter.
Was bedeutet die geonameid?
Eine Zahl, die einen bestimmten Ort weltweit eindeutig identifiziert — vergleichbar mit einer ISBN für Bücher. München hat z. B. 2867714, Wien 2761369. Das ist nützlich, wenn du einen Ort über lange Zeit eindeutig referenzieren willst, denn der Name könnte mehrdeutig sein („Frankfurt" am Main oder an der Oder?), aber die ID nicht.
Die IDs kommen aus dem GeoNames-Projekt, einer freien geographischen Datenbank.
Ich brauche das Land/die Bundesland-Information.
Im Suchergebnis sind country_code (ISO-2-Buchstaben-Kürzel wie „DE", „CH", „AT") und admin1_code (Bundesland/Kanton/Provinz, z. B. „02" für Bayern) immer enthalten. Im Widget kannst du das Land direkt in ein Hidden-Feld schreiben lassen:
<input type="text" name="ort" data-geoapi-place
data-geoapi-country="ort_cc">
Dann liegt $_POST["ort_cc"] nach dem Absenden vor.
Kann ich einen Lade-Indikator zeigen, während die Suche läuft?
Ja. Das Widget feuert ein Event geoapi:fetch-start bevor es eine Anfrage schickt, und geoapi:fetch-end, wenn die Antwort da ist. Damit kannst du z. B. einen Spinner ein- und ausblenden:
<input type="text" name="ort" data-geoapi-place>
<span id="loader" hidden>⏳</span>
<script>
const input = document.querySelector("[data-geoapi-place]");
const loader = document.getElementById("loader");
input.addEventListener("geoapi:fetch-start", () => loader.hidden = false);
input.addEventListener("geoapi:fetch-end", () => loader.hidden = true);
</script>
<script src="https://geoapi.world/dist/geoapi-widget.js"></script>
Dasselbe Prinzip funktioniert für eigene Statusmeldungen, Disable-States auf einem Submit-Button oder Animationen.
Ich möchte sehen, was das Widget tatsächlich abfragt — gibt es eine Debug-Hilfe?
Zwei Wege:
- Live-Demo — auf der Demo-Seite (Tab „Mit Erklärung & API-Sicht") siehst du die rohen API-Aufrufe und JSON-Antworten in Echtzeit, ohne selbst eine Zeile zu schreiben.
- Eigene Konsolen-Ausgabe — ein paar Zeilen im JavaScript:
Beachte:document.addEventListener("geoapi:fetch-end", (e) => { if (e.detail.error) { console.warn("geoAPI-Fehler:", e.detail.error); } else { console.log("geoAPI →", e.detail.results.length, "Treffer für \"" + e.detail.query + "\""); console.log("URL:", e.detail.url); console.log("Antwort:", e.detail.response); } });document.addEventListener(nichtinput...) — die Events bubbeln bis zumdocument-Objekt, also reicht ein einziger Listener.
Wie geht es weiter?
- → Live-Demo — sieh die Werte in Echtzeit, während du tippst.
- → API-Doku — alle Endpunkte und Parameter im Detail.
- → Toolkit zum Download — PHP-Client und Widget-JS.
Fragen oder Probleme? Schreib an ai@rd5.org.