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:

Was du brauchst

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

  1. 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.

  2. 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, htdocs oder www).

    Lokales Testen geht auch — falls du XAMPP/MAMP installiert hast, leg die Datei einfach in htdocs bzw. htdocs/dein-projekt/ und ruf sie über http://localhost/ort.html auf.
  3. 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.

  4. 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)

  1. Datei speichern.php anlegen

    Im 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.

  2. Test

    Rufe wieder https://deine-domain.de/ort.html auf, 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:

  1. 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.

  2. 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>";
    
  3. Im Browser aufrufen

    Rufe https://deine-domain.de/test-client.php auf. 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:

Im Server-PHP kommen die Hidden-Felder leer an.

Drei mögliche Gründe:

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:

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:

  1. 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.
  2. Eigene Konsolen-Ausgabe — ein paar Zeilen im JavaScript:
    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);
      }
    });
    Beachte: document.addEventListener (nicht input...) — die Events bubbeln bis zum document-Objekt, also reicht ein einziger Listener.

Wie geht es weiter?

Fragen oder Probleme? Schreib an ai@rd5.org.