Jak převést adresy na souřadnice zdarma (geokódování z RÚIAN)
Seznam adres v tabulce je k mapě nanic, dokud nemá souřadnice. Placené API na to ale potřeba není: stát zveřejňuje všechna česká adresní místa i s polohou v jednom měsíčním ZIPu. Ukážeme, jak z něj postavit vlastní geokodér a na které pasti v datech narazíte.

Máte v tabulce seznam poboček, zákazníků nebo svozových míst a chcete je dostat do mapy. Chybí jediná věc, souřadnice. První reakce bývá sáhnout po placeném geokódovacím API, jenže u českých adres to ve většině případů není potřeba. RÚIAN obsahuje kompletní seznam adresních míst v ČR včetně polohy a stahuje se zdarma jako CSV. Postavíte z něj geokodér, který běží u vás, nemá limit na počet dotazů a neposílá adresy vašich zákazníků nikam ven.
Co je adresní bod a kolik jich je
Adresní místo je v RÚIAN samostatný objekt s vlastním kódem (kód ADM). Má přiřazenou obec, část obce, případně ulici, číslo domovní a orientační, PSČ a souřadnice. K 31. 8. 2026 jich bylo 3 021 203, z toho 2 614 947 s číslem popisným a 406 256 s číslem evidenčním, což jsou typicky chaty a rekreační objekty.
Stažení: jeden ZIP za celou republiku
ČÚZK publikuje adresní místa jako CSV ve Veřejném dálkovém přístupu, v sekci Výměnný formát. Soubor vzniká jednou měsíčně a nese v názvu datum posledního dne měsíce, denní varianta CSV neexistuje. Celá republika je jeden ZIP kolem 63 MB, uvnitř 6 258 souborů, jeden na každou obec. Stáhnout jde i jediná obec zvlášť, když vám stačí jedno město.
# Cela CR, jeden ZIP (cca 63 MB), uvnitr 6258 CSV po obcich
curl -O https://vdp.cuzk.gov.cz/vymenny_format/csv/20260831_OB_ADR_csv.zip
unzip 20260831_OB_ADR_csv.zip # -> CSV/20260831_OB_*.csv
# Jen jedna obec, cislo v nazvu je kod obce z RUIAN (554782 = Praha)
curl -O https://vdp.cuzk.gov.cz/vymenny_format/csv/20260831_OB_554782_ADR.csv.zipKód obce najdete v číselníku obcí ve VDP nebo v katalogovém záznamu RÚIAN. Pro představu o velikosti: Praha má 134 627 adresních bodů, běžná vesnice jich má pár desítek.
Tři pasti, které v CSV čekají
- Kódování je Windows-1250, ne UTF-8. Bez převodu se z Údolní stane nečitelný paskvil a zpětně to nespravíte. Převádějte hned při rozbalení, ne až v aplikaci.
- Souřadnice jsou kladné a prohozené. S-JTSK má osy obráceně proti tomu, co čeká většina nástrojů, a CSV je navíc uvádí bez znaménka. Do EPSG:5514 patří hodnota ze sloupce
Souřadnice Yna vodorovnou osu, hodnota ze sloupceSouřadnice Xna svislou, a obě se znaménkem minus. Pražský hrad má v CSV744384.54a1042569.73, správně je to tedy bod-744384.54, -1042569.73, po převodu 50,0895 severní šířky a 14,3986 východní délky. - Pár set řádků souřadnice vůbec nemá. Ve snímku z 31. 8. 2026 jich bylo 918. Prázdné pole si většina nástrojů tiše přepíše na nulu, jenže nula v EPSG:5514 leží až u Tallinnu. Takové řádky vyhoďte hned při zpracování.
Z CSV na mapu bez databáze
Nejdřív z 6 258 souborů uděláme jeden a rovnou ho překlopíme do UTF-8. Hlavička musí zůstat jen jedna, proto se ze zbylých souborů bere až druhý řádek dál.
# Hlavicka jednou, zbytek bez hlavicek, vse z Windows-1250 do UTF-8
head -1 CSV/20260831_OB_500011_ADR.csv | iconv -f CP1250 -t UTF-8 > adresy.csv
for f in CSV/*.csv; do tail -n +2 "$f"; done | iconv -f CP1250 -t UTF-8 >> adresy.csvTeď dopočítáme sloupce se správně otočenými souřadnicemi a předáme to nástroji ogr2ogr, který z CSV udělá GeoPackage rovnou reprojektovaný do WGS84 pro web.
# Prida sloupce x, y v EPSG:5514 a vyhodi radky bez souradnic
awk -F';' 'BEGIN{OFS=";"} NR==1{print "x","y",$0; next} \
$17!="" && $18!="" {printf "%.2f;%.2f;%s\n", -$17, -$18, $0}' adresy.csv > adresy_xy.csv
ogr2ogr -f GPKG adresy.gpkg adresy_xy.csv \
-oo X_POSSIBLE_NAMES=x -oo Y_POSSIBLE_NAMES=y \
-s_srs EPSG:5514 -t_srs EPSG:4326 -nln adresyprintf s %.2f v tom awku není kosmetika. Bez něj zapíše awk dlouhá čísla vědeckou notací (-1.04257e+06), GDAL je načte se ztrátou přesnosti a adresy se rozjedou o stovky metrů. Hotový GeoPackage otevřete v QGIS dvojklikem, viz Jak začít s QGIS.Geokodér v PostGIS
Když adresy hledáte opakovaně a programově, patří data do databáze. Postup navazuje na návod Od staženého SHP k dotazovatelné databázi, jen místo importu vrstvy nahrajete CSV a geometrii dopočítáte v SQL.
CREATE TABLE adresy (
kod_adm bigint, kod_obce integer, nazev_obce text,
kod_momc integer, nazev_momc text, kod_mop integer, nazev_mop text,
kod_casti_obce integer, nazev_casti_obce text,
kod_ulice integer, nazev_ulice text, typ_so text,
cislo_domovni text, cislo_orientacni text, znak_cisla_or text,
psc text, souradnice_y double precision, souradnice_x double precision,
plati_od timestamp
);
\copy adresy FROM 'adresy.csv' WITH (FORMAT csv, DELIMITER ';', HEADER true)
ALTER TABLE adresy ADD COLUMN geom geometry(Point, 4326);
UPDATE adresy SET geom = ST_Transform(
ST_SetSRID(ST_MakePoint(-souradnice_y, -souradnice_x), 5514), 4326)
WHERE souradnice_y IS NOT NULL;
CREATE INDEX ON adresy USING GIST (geom);Čísla domovní a orientační nechte jako text, ne jako celé číslo. Budete je porovnávat s tím, co do formuláře napsal uživatel, a k číslu orientačnímu navíc patří písmenný znak z vedlejšího sloupce, takže se stejně skládají jako řetězce. Pro samotné hledání se pak hodí normalizovaná podoba názvů, aby Udolni našlo Údolní. Tady číhá drobná past: funkce unaccent() není v Postgresu označená jako IMMUTABLE, takže ji nejde použít přímo ve funkčním indexu. Řeší to vlastní obalová funkce.
CREATE EXTENSION IF NOT EXISTS unaccent;
-- unaccent() neni IMMUTABLE, v indexu ji musi obalit vlastni funkce
CREATE FUNCTION norm(t text) RETURNS text AS $$
SELECT lower(unaccent('unaccent', t))
$$ LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE;
CREATE INDEX ON adresy (norm(nazev_obce), norm(nazev_ulice), cislo_domovni);
SELECT kod_adm, ST_Y(geom) AS lat, ST_X(geom) AS lon
FROM adresy
WHERE norm(nazev_obce) = norm('praha')
AND norm(nazev_ulice) = norm('vinohradska')
AND (cislo_domovni = '1511' OR cislo_orientacni = '230');Proč hledání na ulici a číslo často selže
Geodata jsou ta snadnější část. Většina práce je v tom, jak lidé adresy píšou. Čtyři případy, na kterých naivní porovnání spolehlivě padá:
- Číslo popisné versus orientační. Adresa Vinohradská 230 v Praze je v datech číslo domovní 1511 a číslo orientační 230. Když porovnáváte jen se sloupcem
Číslo domovní, neuspějete u velké části městských adres. Testujte oba sloupce a počítejte i s tvarem 1511/230. - Skoro polovina adres nemá ulici. Bez názvu ulice bylo 1 443 867 záznamů, tedy zhruba 48 procent všech adresních míst. Ve vesnicích je adresa daná částí obce a číslem popisným, třeba Světlá nad Sázavou, část Dolní Dlužiny, č.p. 1. Dotaz, který vyžaduje vyplněnou ulici, tyhle adresy nikdy nenajde.
- Městské části. Lidé píšou Praha 3 nebo Brno-střed, jenže ve sloupci
Název obceje pořád jen Praha, respektive Brno. Městská část je zvlášť ve sloupciNázev MOMC. Před porovnáním obec ořízněte na základní tvar a městskou část berte jen jako doplňkové kritérium. - Písmeno za číslem. Tvar 12a má číslo a písmeno rozdělené, znak je v samostatném sloupci
Znak čísla orientačního. Při porovnávání si ho musíte zpátky slepit.
Reverzní geokódování: ze souřadnic na adresu
Stejná tabulka umí i opačný směr, tedy najít nejbližší adresu k poloze z telefonu nebo ke kliknutí do mapy. Stačí druhý index nad geografickým typem, aby operátor nejbližšího souseda počítal v metrech a ne ve stupních.
CREATE INDEX ON adresy USING GIST ((geom::geography));
WITH bod AS (
SELECT ST_SetSRID(ST_MakePoint(16.5924, 49.1982), 4326)::geography AS g
)
SELECT nazev_ulice, cislo_domovni, cislo_orientacni, nazev_obce, psc,
round((geom::geography <-> bod.g)::numeric, 1) AS vzdalenost_m
FROM adresy, bod
ORDER BY geom::geography <-> bod.g
LIMIT 1;Kdy má naopak smysl sáhnout po API
Vlastní data se vyplatí na dávkové, opakované nebo offline zpracování. Na pár dotazů denně je jednodušší hotová služba, a někdy potřebujete i to, co SQL neumí, tedy našeptávání a toleranci k překlepům.
- Nominatim nad daty OpenStreetMap je zdarma, ale veřejná instance má tvrdý strop jeden dotaz za sekundu, vyžaduje vlastní identifikaci v hlavičce User-Agent a hromadné geokódování na ní provozní pravidla zakazují. Na větší objem si ji musíte rozjet sami.
- REST API Mapy.com je komerční, ale základní tarif dává 250 000 kreditů měsíčně zdarma a jedno vyhledání adresy stojí 4 kredity, tedy zhruba 62 000 dotazů měsíčně bez placení. Zvládá našeptávání i překlepy.
- Ověření adresy přímo ve VDP je interaktivní formulář na jednu adresu. Hodí se na ruční kontrolu sporných případů, ne na dávku.


