pip install mlnativeCheck your install:
python -m mlnative doctor
python -m mlnative doctor --renderfrom mlnative import Map
with Map(512, 512) as m:
png = m.render(center=[-122.4, 37.8], zoom=12)
with open("map.png", "wb") as f:
f.write(png)Main class for rendering static maps using MapLibre GL Native.
Map(width: int, height: int, pixel_ratio: float = 1.0, timeout: float | None = None)Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
width |
int |
required | Image width in pixels (1-4096) |
height |
int |
required | Image height in pixels (1-4096) |
pixel_ratio |
float |
1.0 |
Pixel ratio for high-DPI (0 < x <= 4) |
timeout |
`float | None` | None |
Raises:
MlnativeError: If dimensions are invalid
Load a map style from URL, file path, or dict.
load_style(style: str | dict[str, Any] | Path) -> NoneParameters:
| Parameter | Type | Description |
|---|---|---|
style |
str |
URL (https://...) or file path |
style |
dict |
MapLibre style JSON object |
style |
Path |
Path to style JSON file |
Example:
# From URL
m.load_style("https://tiles.openfreemap.org/styles/liberty")
# From file
m.load_style("path/to/style.json")
# From dict
m.load_style({"version": 8, "sources": {...}, "layers": [...]})Render the map to PNG bytes.
render(
center: Sequence[float],
zoom: float,
bearing: float = 0,
pitch: float = 0
) -> bytesParameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
center |
[lon, lat] |
required | Map center coordinates as a list or tuple of two finite numbers |
zoom |
float |
required | Zoom level (0-24) |
bearing |
float |
0 |
Rotation in degrees (normalized to 0-360) |
pitch |
float |
0 |
Tilt in degrees (0-85) |
Returns: bytes - PNG image data
Example:
png = m.render(center=[-122.4, 37.8], zoom=12, bearing=45)Render multiple views efficiently (reuses the renderer process).
render_batch(views: list[dict[str, Any]]) -> list[bytes]Parameters:
| Parameter | Type | Description |
|---|---|---|
views |
list[dict] |
List of view dictionaries |
View dict keys:
| Key | Type | Required | Description |
|---|---|---|---|
center |
[lon, lat] |
yes | Map center |
zoom |
float |
yes | Zoom level |
bearing |
float |
no | Rotation (default 0) |
pitch |
float |
no | Tilt (default 0) |
Returns: list[bytes] - List of PNG images
Note: Per-view GeoJSON updates are not supported in batch mode. Use set_geojson() followed by render() in a loop when each image needs different source data.
Example:
views = [
{"center": [0, 0], "zoom": 5},
{"center": [10, 10], "zoom": 8, "bearing": 45},
]
pngs = m.render_batch(views)Calculate center and zoom to fit geographic bounds.
fit_bounds(
bounds: Sequence[float],
padding: int = 0,
max_zoom: float = 24
) -> tuple[list[float], float]Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
bounds |
(xmin, ymin, xmax, ymax) |
required | Bounding box in degrees as a list or tuple |
padding |
int |
0 |
Padding in pixels |
max_zoom |
float |
24 |
Maximum zoom level |
Returns: tuple[[lon, lat], zoom]
Example:
bounds = (-122.5, 37.7, -122.3, 37.9)
center, zoom = m.fit_bounds(bounds, padding=50)
png = m.render(center=center, zoom=zoom)Update GeoJSON data for a source in the current style.
set_geojson(
source_id: str,
geojson: dict[str, Any] | str | BaseGeometry
) -> NoneParameters:
| Parameter | Type | Description |
|---|---|---|
source_id |
str |
Source ID in the style |
geojson |
dict |
GeoJSON object |
geojson |
str |
JSON string |
geojson |
BaseGeometry |
Shapely geometry |
Note: Style must be loaded as a dict, not a URL.
Example:
from shapely import Point
m.load_style(style_dict)
m.set_geojson("markers", Point(-122.4, 37.8))
png = m.render(center=[-122.4, 37.8], zoom=12)Release resources. Called automatically when used as context manager.
Located in mlnative.geo:
Helpers validate longitude/latitude ranges and common wrong shapes near the input boundary. Coordinate helper inputs are explicit tuples: (lng, lat) for GeoJSON order or (lat, lng) for GPS order.
Create a GeoJSON Point feature.
from mlnative.geo import point
sf = point(-122.4, 37.8, {"name": "San Francisco"})Create a GeoJSON FeatureCollection.
from mlnative.geo import feature_collection
fc = feature_collection([point(-122.4, 37.8), point(-74.0, 40.7)])Convert bounds tuple to a GeoJSON Polygon feature.
from mlnative.geo import bounds_to_polygon
poly = bounds_to_polygon((-122.5, 37.7, -122.3, 37.9))Create FeatureCollection from (lng, lat) tuples.
from mlnative.geo import from_coordinates
fc = from_coordinates([(-122.4, 37.8), (-74.0, 40.7)])Create FeatureCollection from (lat, lng) GPS tuples.
from mlnative.geo import from_latlng
fc = from_latlng([(37.8, -122.4), (40.7, -74.0)]) # GPS orderRun installation checks with:
python -m mlnative doctorUse --render to start the native renderer and render a tiny local-style PNG without remote tile access:
python -m mlnative doctor --renderThe packaged wheel should find mlnative/bin/mlnative-render-<platform>-<arch>. PATH lookup is disabled unless MLNATIVE_USE_SYSTEM_BINARY=1 is set.
Base exception for all mlnative errors.
from mlnative.exceptions import MlnativeError
try:
m.render(center=[999, 999], zoom=12)
except MlnativeError as e:
print(f"Error: {e}")Common cases:
- Missing native binary: install a platform wheel or build with
just build-rust. - Protocol version mismatch: rebuild the Rust binary so it matches the Python package.
- Renderer timeout: the daemon is stopped to avoid stale responses; create a new
Mapto retry. - GeoJSON source update on URL style: load the style JSON as a dict first.
The included servers are examples, not production services. They bind to loopback and use style IDs from an allowlist. Public deployments should add authentication, quotas/rate limits, caching, concurrency budgets, and explicit network egress controls for style/tile requests.
| Constant | Value | Description |
|---|---|---|
DEFAULT_STYLE |
OpenFreeMap Liberty URL | Default map style |
MAX_DIMENSION |
4096 |
Maximum width/height |
MAX_ZOOM |
24 |
Maximum zoom level |
MAX_PITCH |
85 |
Maximum pitch degrees |
Python (mlnative)
↓ JSON over stdin/stdout
Rust (mlnative-render daemon)
↓ FFI
MapLibre Native (C++ core)
↓
Pre-built amalgam libraries
The native renderer uses pre-built libraries with statically linked dependencies (ICU, libjpeg, libpng, etc.), eliminating system dependency issues.