Русский · English
Ready-to-run examples of the forward geocoding API in six languages: Python, TypeScript (Node.js), Go, Java, C#, PHP. Turn a street address into latitude and longitude — from a free-form string, from structured fields, or in a batch of up to 1000 addresses per call. Every response carries the parsed address structure, the coordinate precision level and the administrative hierarchy from the Russian state address registry (GAR/FIAS).
Every example runs immediately — no sign-up, no key, no card. A public demo key is hard-coded.
git clone https://github.com/atlorium-api/geocoding-api-client
cd geocoding-api-client/python && pip install -r requirements.txt && python main.pyДемо-ключ: ответы сгенерированы (моки), не данные реестра.
Запрос: Казань, улица Баумана, 13
Найдено вариантов: 2
1. Респ Татарстан, г Казань, ул Баумана, 13
55.788226, 49.121984 · layer=address · precision=exact
Индекс 420111 · placeId 11111111-2222-3333-4444-555555555555
[USE] Точная координата дома 13
2. Респ Татарстан, г Казань, ул Баумана
55.789512, 49.120331 · layer=street · precision=street
Индекс 420111 · placeId 66666666-7777-8888-9999-000000000000
[REJECT] Дома в данных нет — отдан центр улицы
Пакетная выгрузка (3 строки):
1. Казань, улица Баумана, 13 → 55.788226, 49.121984 (exact)
2. Москва, Тверская 1 → 55.788226, 49.121984 (exact)
3. улицы с таким названием не существует → не найдено
Отправлено 3, найдено 2, списано единиц 2 — ненайденные строки не тарифицируются.
Адресные данные: ГАР/ФИАС (ФНС России), открытые данные. Координаты: © участники OpenStreetMap (ODbL).
The examples print in Russian, because the addresses and the registry data they describe are Russian. The API itself is language-neutral.
The demo key answers with a fixed demonstration set (one house in Kazan and everything around it) rather than with a registry lookup — which is why "Москва, Тверская 1" also resolves to the Kazan house above. That is deliberate: the coordinates in the set are real and consistent across every mode, so the response can be put on a map and parsed for real. Swap in a live key and the same code starts searching the registry.
Enriching an existing address database with coordinates, plotting orders on a map, computing distance and delivery cost, assigning customers to service areas, feeding a point into a routing engine.
The examples do more than print JSON — they apply the data: each one contains an assessCoordinate() function that reads layer together with precision and returns a verdict on whether the coordinate may be pinned to a specific building (USE), needs human review (VERIFY) or is unfit for building-level use (REJECT). It also compares the house number in the response with the one in the request: the service deliberately answers "house 13" when asked for "13к2", and that has to be noticed rather than missed.
Try the API without cloning anything:
curl -H "Authorization: Bearer ak_sandbox_demo_mockdata_v1" \
"https://atlorium.com/api/geocodeforward?text=Казань,%20улица%20Баумана,%2013"| Language | Run | Requires |
|---|---|---|
| Python | pip install -r requirements.txt && python main.py |
Python 3.10+ |
| TypeScript / Node.js | npm install && npm start |
Node.js 20+ |
| Go | go run . |
Go 1.22+ |
| Java | java Main.java |
JDK 11+ (no dependencies) |
| C# | dotnet run |
.NET 8+ |
| PHP | php main.php |
PHP 8.1+ |
Pass your own address as an argument: python main.py "Москва, Тверская 1"
The key travels in the Authorization header:
Authorization: Bearer YOUR_KEY
| Key | What it does |
|---|---|
ak_sandbox_demo_mockdata_v1 |
Demo key. Public, shared by everyone. Returns a fixed demonstration set, charges nothing, requires no account. Responses are deterministic, so stable tests can be written against them. |
| Live key | Real registry lookups. Get one at atlorium.com |
Switching to a live key requires no code change — every example reads an environment variable:
export ATLORIUM_API_KEY="ak_your_live_key"Every sandbox response is stamped with X-Atlorium-Sandbox: true, so a demonstration set can never be mistaken for a real lookup.
Base URL: https://atlorium.com
| Method | Path | Purpose |
|---|---|---|
GET |
/api/geocodeforward |
Coordinates from a free-form address string |
GET |
/api/geocodeforward/structured |
Coordinates from an address split into fields |
POST |
/api/geocodeforward/batch |
Up to 1000 addresses in one call |
GET |
/api/geocodeforward/place |
Object card by identifier, optionally with a GeoJSON boundary |
GET |
/api/geocodeforward/postcode |
What a postal code covers |
| Parameter | Type | Description |
|---|---|---|
text |
string | Required. The address as one string: Казань, улица Баумана, 13. From 3 to 250 characters |
size |
int | How many candidates to return. Default 5, maximum 20. Out-of-range values are clamped to the boundary rather than rejected |
exactOnly |
bool | Keep only exact house matches (precision = exact). Default false |
The house number is split off from the street name right to left, by the last standalone number — so street names that begin with a number are parsed correctly.
| Parameter | Type | Description |
|---|---|---|
address |
string | Street with house number: улица Баумана, 13 |
locality |
string | Locality: Казань |
region |
string | Region of the Russian Federation |
postalCode |
string | Postal code: 420111 |
size |
int | How many candidates to return |
exactOnly |
bool | Exact house matches only |
You do not have to fill every field. A request with no address field at all is rejected with 400. The postal code acts as a check, not a filter: if it disagrees with what was found, the results are still returned — postal codes in client databases go stale more often than addresses do. This mode is billed at its own rate.
{
"queries": ["Казань, улица Баумана, 13", "Москва, Тверская 1"],
"sizePerQuery": 1,
"exactOnly": false
}| Parameter | Type | Description |
|---|---|---|
queries |
string[] | Required. Up to 1000 address strings. A larger batch is rejected as a whole (400) — extra rows are never dropped silently |
sizePerQuery |
int | Candidates per row. Default 1 |
exactOnly |
bool | Exact house matches only |
The response holds exactly as many items as the strings sent, in the same order, and each item also carries its original string in query. A row with no match gets an empty matches list and does not abort the batch.
| Parameter | Type | Description |
|---|---|---|
placeId |
string | Required. The placeId value from any earlier geocoding response |
includeBoundary |
bool | Also return the object boundary as GeoJSON. Costs an extra unit of work, and only if a boundary was actually returned |
The identifier is assigned by the state registry and never changes, which makes a repeat lookup cheaper and more reliable than a fresh search.
| Parameter | Type | Description |
|---|---|---|
code |
string | Required. Exactly six digits: 420111 |
size |
int | How many objects to return. Default 20, maximum 100 |
Returns the locality and the streets the postal code belongs to. Houses are not returned — there are tens of thousands per code, and such a response would not answer the question asked.
A search response: query, matches[], attribution.
matches item field |
Type | Contents |
|---|---|---|
placeId |
string | Registry identifier of the object. Stable — usable as a foreign key |
label |
string | The address as one line, as recorded in the registry |
name |
string | The object's own name (house number, street or city name) |
houseNumber |
string | House number, when a house was found |
street |
string | Street |
postalCode |
string | Postal code |
point |
object | The coordinate: { latitude, longitude } |
layer |
string | What was found: address — a house, street — a street, locality — a settlement |
precision |
string | Whose coordinate this is. The key field — see the table below |
admin |
object | Registry hierarchy: { region, county, locality, street } |
parentPlaceId |
string | Identifier one level up (street for a house, city for a street) |
distanceKm |
number | Distance to the requested point. Always null in forward geocoding — there is no point to measure from |
| Value | Meaning | Safe to pin to a building |
|---|---|---|
exact |
The coordinate of the house itself | Yes |
range |
The number was interpolated between neighbouring houses, or the match was partial (asked for "13к2", the registry holds a single record "13") | With review |
street |
The house is missing from the data, the street centre is returned | No |
locality, area |
A settlement or coarser | No — the service treats such results as unusable and answers 404 free of charge |
The levels are ordered best to worst. There is deliberately no single "confidence" number: it would be derived from the precision level by reverse arithmetic, and different values of it would mean the same thing.
attribution is the data-source credit line. Displaying it is mandatory — the licence of the source datasets requires it. All six examples print it as the last line.
| Field | Type | Contents |
|---|---|---|
items |
array | One entry per submitted row, in the same order |
requested |
int | How many rows were sent |
found |
int | How many rows produced a match |
billedUnits |
int | Units charged — exactly as many as were found |
| Code | Cause | What to do |
|---|---|---|
400 |
The string is empty, shorter than 3 characters, longer than 250, or the batch exceeds 1000 rows | Fix the request; retrying unchanged is pointless |
401 |
Key missing, expired or invalid | Check the Authorization header |
402 |
Not enough credits | Top up at atlorium.com |
404 |
Address not found, or what was found is coarser than street level. Not charged | Refine the address or accept "no coordinate" as the answer |
429 |
Rate limit exceeded | Retry with a delay |
503 |
The geocoder is temporarily unavailable. Not charged | Retry later |
Note that 404 also covers the case where candidates existed but all were too coarse. For the client both mean the same thing — there is no usable coordinate — so they share one code; the reason itself travels in the response body in plain language.
All six examples map the codes to human-readable causes — see the AtloriumError class.
Pay-as-you-go, no subscription. Only a found result is charged: "not found", results coarser than street level, invalid input and service failures cost nothing. In batch mode you pay for as many rows as were actually found, and that number comes back in billedUnits, so the invoice can be reconciled rather than taken on trust.
The structured mode, the object card and the postal-code lookup are billed at their own rates, because their cost differs. Current prices and limits: atlorium.com/pricing.
How do I geocode a Russian address? Send the address as a string to GET /api/geocodeforward and read matches[0].point. Read precision in the same breath — it tells you whether that is the house itself or the centre of a street.
How is this different from the GAR/FIAS and address standardization services? Geocoding adds coordinates to an address. For the official address text and registry records use GAR/FIAS; for parsing a messy address string into components use address standardization. Three different jobs, not interchangeable.
Does it cover addresses outside Russia? No. The data is loaded for Russia only; a foreign address returns "not found" free of charge.
How do I geocode tens of thousands of rows? Use batch mode in chunks of up to 1000 rows. Order is preserved, unmatched rows neither abort the batch nor cost anything.
What does precision: range mean, can I trust that point? Either the house number was interpolated between neighbours, or the match was partial ("13к2" requested, only "13" on record). The point is next to the right building but not necessarily on it. If an approximate coordinate is worse than none, set exactOnly=true.
Why is there no single confidence score? Because it adds nothing: it would be derived from the precision level by reverse arithmetic, and its different values would mean the same thing. Instead of the illusion of measurement, the service returns what is actually known — whose coordinate this is.
Do I have to register to try it? No. The demo key is public and needs no account — but it returns a fixed demonstration set rather than a registry lookup.
Coordinates are rarely needed on their own. The same account and key also give you:
- Reverse geocoding — address from coordinates, neighbouring houses, landmarks around a point
- GAR/FIAS addresses — search and normalization against the state address registry
- Address standardization — parsing a messy address string into levels with a quality score
- IP geolocation — location from an IP when you have no address yet
- Weather data — weather for the point you just resolved
- EGRUL/EGRIP company registry — company card by INN, legal address included
Full catalogue — atlorium.com
- API documentation (Swagger): atlorium.com/geoAPI
- Service description: atlorium.com/geoDescription
- Web interface: atlorium.com/geoGUI
- OpenAPI specification: geocodeforward_en-US.json
- Support: support@atlorium.com
MIT — take the code and use it however you like, commercial projects included.