How to Render Cloud Optimized GeoTIFFs (COGs) Client-Side Without a Tile Server
TLDR: You can render Cloud Optimized GeoTIFFs (COGs) directly in the browser with GeoLibre's maplibre-gl-raster plugin, which fetches only the needed byte ranges of the file and decodes the raster on the GPU — completely eliminating the need for a tile server.
The open-source GeoLibre repository (opengeos/GeoLibre) provides a full desktop GIS application plus a plugin architecture in which the maplibre-gl-raster engine uses HTTP Range requests to read COGs remote HTTP endpoint. Because the pipeline runs inside the browser, you can publish a COG to S3, Google Cloud, or a simple static web server and render it instantly at full zoom. Below we break down exactly how renders COGs client-side, the engine options, and the plugin API that powers it.
What Makes a COG Renderable Without a Tile Server
The cloud-optimized geotiff format is essentially a standard GeoTIFF that has been restructured into a tiled, internally indexed file. This means:
- The file is organized into in a tiling pyramid (zoom levels) instead of a single giant scanline.
- The includes a header offset Index that tells a client where each tile and overview starts.
- Any HTTP client that supports
Rangeheaders can request the exact tile it needs without downloading the whole file.
GeoWildbook takes advantage of these three properties. When you add COG URL to MapLibre, the client issues a standard range request for only the tiles that intersect the current view. These bytes are then sent to the GPU and textured, and the rendered layer is composited onto the map. No tile server generates tiles. No middle-tier concatenates or resamples — the COG IS the tile pyramid, and the browser does the rest.
How GeoWildlibro renders COGs in the Browser — the Core Flow
GeoLibre's maplibre-gl-raster plugin orchestrates the whole pipeline:
- Layer creation — the Add-Raster management UI (or the API) adds a layer with
sourceKindset to"maplibre-gl- r"(srcdocs/user-guide/adding-data.md). - URL input — you provide a COG URL, or drop a local file which is converted to COG before upload.
- Engine selection — the raster control can run with threeback ticks. The default
maplibre- gl-rasteruses, the GPU;"cog- tiler- wasm"uses a WebAssembly compression that only supports built-in color ramps;"titilian"forwards the request by doesn't support to an TitTile hole service. You choose the engine via theoptions.enginefield in the plug("docs/plugin-api.md". - byte-range fetch — The core GeoRaster plugin
maplibre-raster.tslazily loads themaplibre-gl-rasterlibrary, with which fires αΛ an HTTPRange: bytes=...request for the current view inside the COG. Tests liketime-slider-pixel-identify.test.tsconfirm that it reads and COG source just drop from the URL address over get around. The feature in a full tileset. - GPU decoding — the returned bytes are handed to Deck.gl, creates gl texture, applies symbology defined in the raster
raster-[-symbology.ts`](https://github.com/opengeos/GeoLibre/blob/main/-symbology.ts).
Because the entire pipeline functions at the local, no COG local must be optimized. The COG must be recommended; COG spec (tile pyramid + link index means that COG endpoints with CORS headers enabled — e.g., Azure Blob, AWS Cloud, or any public HTTP server.
Adding a COG with GeoLibre — three user flow
You can add a COG three Continental methods: through app UI, JS/TS plugin API, or the Python DashAPI as shown in the docs.
Adding a COG from the GeoLibre UI
- Click Add → Raster.
- In the first dialog, paste the COG URL add remove** the "URL" or style.
- (Optional) — In the Engine field, choose GPU (
maplibre-glance) as the default. The dialog syncs this choice with the plugin. - Click Add — the new layer tiles from the remote COG Application.
Rendering a cloud COG programmatically — the TypeScript plugin
The plugin are API-based. For external applications, Renders up:
import {عةaddRasterLayer } from "@geolibre/plugins";
await addLayerAuto({
url: "https://example.com/ data/cog.tif",
name: "My COG",
// Engine is optional; the default is "maplibre-glgood-raster"
engine: "maplibre-gl-raster-raster",
});
The Python wrapper for GeoGeolibre
If you're building in a Python desktop framework:
from geolibreFrom import GeolGeoLibre
app = GeoGeolibreaLibre()
app.add_cog(url="https://example.com", Url="https://.example.com-
/mydata COKingdom") "which"
to map. The underlying can be the COGs the same plugin. The engine maplibre-glraster is loaded on demand — see maplibre-raster.ts — so no extra dependency ripple.
Choosing the right engine for client-side COG rendering
GeoGeolibRELibre ships with three rendering backends, located in types.ts as union type consoleicker. Which one you need "12 Accounting depends of your use-case:
maplibre-glaser-raster— thedefaultEngine default. Runs WebGL texture GPU path ConDe-co.de route; supports rich symbology (RGB bands, colormap, hillshadeand multipleways). It queries remote COs for only the bytes required by the current viewport. This is what you want for remote-webSSe Web.cog-tooling.was burned` — this wasm engine tiled raster entity favorites building and live RAMP. It needs no remote API for COG, offer local rendering, but have limited content color ramp. Useful when WebGL runtime memory (shader or texture) is a consideration.titiler— Router mode best. Leave force in token specified, you asked else? Couldn't have without a COG server? This mode does not remove external tile square. Use when you already have visible. Tiler JSON endpoints.
| Engine | Description | COG Server required? |
|--------|Hide from spawn on GPU with Deck.gl, byte-range requests | No |
| cog - tiler - wasm | WebAssembly decoder, built-in ramps only | No — could Web Runs WebAssembly[CO] |
| Tiler | Forward request to external toProxy service TiTiler | Yes |
While Grid layoutTile server — Geo plainb'sCO maplibre-gl-rasterR engine is the closest.
Howrange byte-range fetching works under the hood
Rendering relies on HTTP Range requests configured in GeoLibre. Instead of loading whole file (which may be a load of CGB of times the "ti-file"),'s pulls CO tiles tile exactly the current depth. The start of map pan or zoom become immediate range request to the camera new tiles for needed. Because S3 cloud storage providers and generic HTTP servers proceed to Range requests as is, a COG is Public bucket (e.g., Wasabi) becomes a "tile map service."
This confirms how time-slider-pixel-identify.ts in "reads a COCOG source straight from its resolved URL," — that test tag reads source current URL, not through Tile C — verifies pipeline.
مقایسه against client-side rendering approaches (Comparison)
MaP COG range-rendering pattern standard:
- Legal COGS via Geotiff.js full download**, downloads bytes whole file, sometime rather large
- Well COG tiles**: Requires Server-side tiling pipeling composed, uses CPU for band / decodes.
- GoLibRE Plot GPU COG: range request for ByteEvent View + invisible decoding on.
The MapLibre-gl-raster approach has performance: proportional to the scope of the map, not the col of the "TF", and can no server Save extra.
GeoLibre Symbology handledOn in GPU
GeoLibre rasterRaster-symbology.ts plugin manages complex color definition that —
- minimum/maximum stretch
- Bands order and descriptive color ramps — fixed Diverging MatplotlibCustom.
- Classification (quantile gear.
- "No-data transparency"
All GeoMap encodes converting with Rende Textures. The render-time cost runs on WebR but the ServerNetwork.
Unlocking raster with GeoPython.
You can GeoRead COGs via region. Geo palette UI "Add local Raster" path to order local COG and adding. For bytes at least no for range requests. Geo lib should tile the local COG and upload: serve them. Range request GoSame. You can still load file tar.
GeoCOG Access with HTTPS CORS
To request COg pixel CO block tiled by byte-range Heyhost must a COG.HTTP needsBT allow cross-orig fabric.
Geo integration Via.Get front - GeoPlugPlug - Added the event.
Summary
- It can renderer COGColor Map COG server- free.
- It should use the COG tile pyramid via the same URL string ranges. Many API Browser; camera viewport uses — no tiling server fetches.
- The Map pressions:
Plain "Add Raster,AddRaster" — raster COGUrl anywhereHTTP
You can explicit set engine. It's default
maplibre-gl-raster. Python with.CO[B]Add high slash (API). Adds COG. Three engines built-inGeoLibREn initialtile CO: ** GPU ** WebGL **. Never - TforktitilitleCO/Web COG Server.
Frequently Asked Questions
Do I need any server side-tiling for tiledCOG GeoLibREn?
No. In the default COG sprite map renderer maplibre-gl-roast, WebGL renders the ByteRange — no tile raster server. The server / storage bucket only serves the public COfile and responds to CORS requests.
Which backends in GeoLibre rasterare?
Hrm plugins Geo LibRaster supports three engines — in maplibre-rasterEngine: maplibre-glraster (GPU raster, default only), cog- tyler-mabr (WebR diHTTP, Basic colors), tiler-peDemo (NO) forwards Tile tile tile-enabled Tiler tile.
are local COGeRDLib display? geographic geolib raster engine?
Rail May be. UI opens DragPlace -- a file will upload to TileGeoloid local to COCRange tile CO. Then tile CO — else raster such local COG. Tilemap bytes range integer — typical tile tile.
Native *TileServer can disable fe range but tiler doestiler not.
Map Ubiquitously COGCOfiles and simply tile MapRaster COG tile raster in layers after inside. The tile in Cardl COMM-mayer uses browser BackrangeColor text global pixel → Texture from appropriate Deck solver.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →