geeViz.esriLib

ArcGIS / Esri REST services client for geeViz.

Bridges three Esri service types into the existing geeViz viewer with no JavaScript changes required. The viewer already supports both tileMapService (for raster tiles) and geoJSONVector (for vector features) layer types.

Service type

Mechanism

Image Service

Map.addTileLayer("<url>/tile/{z}/{y}/{x}")

Map Service (cached)

Map.addTileLayer(...) — same tile path

Feature Service (≤ max_features)

Fetch <url>/query?f=geojsonMap.addLayer(geojson_dict)

Feature Service (> max_features)

ValueError with remediation message

Public API — 7 functions + 1 constant:

import geeViz.esriLib as el

# Discover data on any ArcGIS Portal
results = el.searchPortal("naip 2023")                  # IIPP (default)
results = el.searchPortal("naip 2023", portal="agol")   # ArcGIS Online
results = el.searchPortal("naip 2023",
                          portal="https://myagency.gov/portal")

# Available portals
el.PORTALS.keys()   # iipp, agol, usgs, noaa, usfs, nasa

# Inspect any service
meta = el.getServiceMetadata("https://.../ImageServer")

# Add to the geeViz map (auto-dispatches by service type)
el.addEsriService(result_or_url)

# Or call the typed helpers directly
el.addEsriImageService("https://.../ImageServer", name="NAIP 2023")
el.addEsriFeatureService("https://.../FeatureServer/0",
                         max_features=2000, where="STATE='UT'")
el.addEsriMapService("https://.../MapServer")

Token-gated portals:

# Obtain a token first:
#   POST <portal>/sharing/rest/generateToken
#     username=...&password=...&client=requestip&expiration=60&f=json
token = "..."
el.searchPortal("classified data", token=token)
el.addEsriFeatureService(url, token=token)

Copyright 2026 Ian Housman

Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License. You may obtain a copy of the License at

Module Attributes

PORTALS

Module-level dict mapping short names to portal base URLs.

Functions

addEsriFeatureService(url_or_result[, ...])

Fetch and add an ArcGIS Feature Service layer as a GeoJSON vector layer.

addEsriImageService(url_or_result[, ...])

Add an ArcGIS Image Service as an XYZ tile layer to the geeViz map.

addEsriMapService(url_or_result[, name, ...])

Add a cached ArcGIS Map Service as an XYZ tile layer to the geeViz map.

addEsriService(url_or_result[, viz_params, ...])

Auto-detect the Esri service type and call the appropriate add helper.

getServiceMetadata(url[, token])

Fetch and return the JSON metadata for any ArcGIS REST service.

searchPortal(query[, portal, limit, ...])

Search any ArcGIS Portal for hosted services.

geeViz.esriLib.PORTALS: dict[str, str] = {'agol': 'https://www.arcgis.com', 'iipp': 'https://imagery.geoplatform.gov/iipp', 'nasa': 'https://nasa.maps.arcgis.com', 'noaa': 'https://coastalatlas.noaa.gov', 'usfs': 'https://data.fs.usda.gov/geodata', 'usgs': 'https://www.sciencebase.gov/sciencebase'}

Module-level dict mapping short names to portal base URLs.

Add your own at runtime:

from geeViz.esriLib import PORTALS
PORTALS["myagency"] = "https://gis.myagency.gov/portal"
geeViz.esriLib.searchPortal(query: str, portal: str = 'iipp', limit: int = 20, data_only: bool = True, raw_q: str | None = None, token: str | None = None, **filters: Any) list[dict[str, Any]][source]

Search any ArcGIS Portal for hosted services.

Uses the standard /sharing/rest/search endpoint present on ArcGIS Online, IIPP, and any ArcGIS Enterprise install.

Parameters:
  • query (str) – Free-text search query (e.g. "naip 2023", "fire perimeter").

  • portal (str, optional) – Either a short name from PORTALS ("iipp", "agol", "usgs", "noaa", "usfs", "nasa") or a full portal base URL. Defaults to "iipp".

  • limit (int, optional) – Maximum results to return (1–100). Defaults to 20.

  • data_only (bool, optional) – When True (default), appends a bundled exclusion list that filters out non-data items (styles, web apps, dashboards, etc.) so results are datasets only. Set to False to search without restrictions.

  • raw_q (str, optional) – If supplied, overrides the assembled query string entirely — ignores query, data_only, and filters. Use for portal query DSL power users.

  • token (str, optional) – ArcGIS token for secured portals. Omit for public services. Obtain via POST <portal>/sharing/rest/generateToken.

  • **filters – Extra ArcGIS search filters forwarded verbatim as query params (e.g. sortField="title", sortOrder="asc", bbox="-120,35,-110,42").

Returns:

Parsed portal items. Each dict includes:

  • id (str): Item ID.

  • title (str): Item title.

  • type (str): Esri item type (e.g. "Image Service", "Feature Service").

  • snippet (str): Short description.

  • tags (list of str): Associated tags.

  • url (str): Service endpoint URL (may be "" if not set).

  • owner (str): Portal username of the owner.

  • created (int): Unix timestamp (ms) of item creation.

  • modified (int): Unix timestamp (ms) of last modification.

  • thumbnail (str or None): Thumbnail URL, or None if absent.

  • _raw (dict): Full raw portal item dict for advanced access.

Return type:

list of dict

Example:

import geeViz.esriLib as el

# Search IIPP for NAIP imagery (default portal)
results = el.searchPortal("naip 2023", limit=10)
for r in results:
    print(r["title"], r["type"], r["url"])

# ArcGIS Online
results = el.searchPortal("wildfire perimeter", portal="agol")

# Custom Enterprise portal
results = el.searchPortal("hydrology",
                          portal="https://gis.mystate.gov/portal")

# Raw portal query DSL (bypasses data_only and filters)
results = el.searchPortal("", raw_q='type:"Feature Service" owner:USGS')
geeViz.esriLib.getServiceMetadata(url: str, token: str | None = None) dict[str, Any][source]

Fetch and return the JSON metadata for any ArcGIS REST service.

Appends ?f=json to the URL and returns the parsed response. Works for ImageServer, FeatureServer, MapServer, and any sub-layer URL (e.g. /FeatureServer/0).

Parameters:
  • url (str) –

    ArcGIS service endpoint, e.g.:

    "https://naip.services.arcgis.com/.../ImageServer"
    "https://services.arcgis.com/.../FeatureServer/0"
    "https://server.arcgisonline.com/.../MapServer"
    

  • token (str, optional) – ArcGIS token for secured services.

Returns:

Parsed service metadata. Common keys vary by service type:

  • name (str): Service name.

  • type (str): Layer geometry type (Feature Services).

  • fields (list): Schema fields (Feature Services).

  • extent (dict): Spatial extent.

  • spatialReference (dict): Spatial reference info.

  • minScale, maxScale (int): Scale range.

  • capabilities (str): Comma-separated capabilities string.

Return type:

dict

Raises:
  • ConnectionError – If the URL is unreachable.

  • ValueError – If the response is not valid JSON.

Example:

import geeViz.esriLib as el

meta = el.getServiceMetadata("https://.../ImageServer")
print(meta["name"])
print(meta["extent"])

# FeatureServer layer 0
meta = el.getServiceMetadata("https://.../FeatureServer/0")
print([f["name"] for f in meta.get("fields", [])])
geeViz.esriLib.addEsriImageService(url_or_result: str | dict, viz_params: dict | None = None, name: str | None = None, token: str | None = None) None[source]

Add an ArcGIS Image Service as an XYZ tile layer to the geeViz map.

Constructs the ArcGIS tile URL pattern <service_url>/tile/{z}/{y}/{x} and calls geeViz.geeView.Map.addTileLayer.

Note

ArcGIS tile URLs use {z}/{y}/{x} order (y before x), not the XYZ standard {z}/{x}/{y}. This function emits the correct ArcGIS order automatically.

Parameters:
  • url_or_result (str or dict) –

    Either:

    • A bare service URL, e.g. "https://naip.services.arcgis.com/.../ImageServer"

    • A searchPortal() result dict (the "url" key is used).

  • viz_params (dict, optional) – Forwarded to addTileLayer as keyword arguments. Supported keys: opacity (float), visible (bool), max_zoom (int).

  • name (str, optional) – Layer name shown in the geeViz layer list. Defaults to the last segment of the service URL.

  • token (str, optional) – ArcGIS token appended to tile requests as ?token=<>.

Example:

import geeViz.esriLib as el
import geeViz.geeView as gv

el.addEsriImageService(
    "https://naip.services.arcgis.com/.../ImageServer",
    name="NAIP 2022",
    viz_params={"opacity": 0.85},
)
gv.Map.centerObject(gv.ee.Geometry.Point([-111.89, 40.77]), 12)
gv.Map.view()
geeViz.esriLib.addEsriMapService(url_or_result: str | dict, name: str | None = None, token: str | None = None, viz_params: dict | None = None) None[source]

Add a cached ArcGIS Map Service as an XYZ tile layer to the geeViz map.

Cached Map Services expose the same /tile/{z}/{y}/{x} tile endpoint as Image Services and are handled identically. Dynamic (non-cached) Map Services do not serve tiles this way; for those, use addEsriFeatureService() on the individual sub-layer.

Parameters:
  • url_or_result (str or dict) – Service URL or searchPortal() result dict.

  • name (str, optional) – Layer name. Defaults to last URL segment.

  • token (str, optional) – ArcGIS token for secured services.

  • viz_params (dict, optional) – opacity, visible, max_zoom.

Example:

import geeViz.esriLib as el

el.addEsriMapService(
    "https://server.arcgisonline.com/ArcGIS/rest/services/"
    "World_Imagery/MapServer",
    name="ESRI World Imagery",
)
geeViz.esriLib.addEsriFeatureService(url_or_result: str | dict, viz_params: dict | None = None, name: str | None = None, max_features: int = 1000, where: str = '1=1', token: str | None = None) None[source]

Fetch and add an ArcGIS Feature Service layer as a GeoJSON vector layer.

Hits <url>/query?f=geojson&where=<where>&outSR=4326 and passes the returned GeoJSON directly to geeViz.geeView.Map.addLayer.

Warning

Always performs a returnCountOnly=true pre-flight before fetching geometry. If the result count exceeds max_features, a ValueError is raised with a concrete remediation message.

Parameters:
  • url_or_result (str or dict) – Feature Service or sub-layer URL (e.g. ".../FeatureServer/0"), or a searchPortal() result dict. If the URL points to the FeatureServer root rather than a specific layer, /0 is appended automatically.

  • viz_params (dict, optional) – Passed to Map.addLayer as the viz dict. Supports all geeViz vector viz keys ("color", "strokeColor", "fillColor", "opacity", "strokeWidth", "layerType", etc.).

  • name (str, optional) – Layer name. Defaults to last URL segment.

  • max_features (int, optional) – Hard cap on feature count. If the service has more than this many features matching where, a ValueError is raised. Defaults to 1000. Increase with care — very large GeoJSON payloads can slow the viewer.

  • where (str, optional) – SQL WHERE clause sent to the service for server-side filtering. Defaults to "1=1" (all features). Example: where="STATE_FIPS='06'" (California only).

  • token (str, optional) – ArcGIS token for secured services.

Raises:
  • ValueError – If the feature count exceeds max_features.

  • ConnectionError – If the service URL is unreachable.

Example:

import geeViz.esriLib as el
import geeViz.geeView as gv

# Simple fetch — all features up to default cap
el.addEsriFeatureService(
    "https://services.arcgis.com/.../FeatureServer/0",
    name="Wildfire Perimeters",
)

# Filter server-side to stay under the cap
el.addEsriFeatureService(
    "https://services.arcgis.com/.../FeatureServer/0",
    where="YEAR_=2023 AND GIS_ACRES > 10000",
    name="Large 2023 Fires",
    max_features=500,
)

gv.Map.view()
geeViz.esriLib.addEsriService(url_or_result: str | dict, viz_params: dict | None = None, name: str | None = None, token: str | None = None, max_features: int = 1000, where: str = '1=1') None[source]

Auto-detect the Esri service type and call the appropriate add helper.

Inspects the URL path (and falls back to the service metadata) to determine whether url_or_result is an Image Service, Feature Service, or Map Service, then delegates to addEsriImageService(), addEsriFeatureService(), or addEsriMapService().

Parameters:
  • url_or_result (str or dict) – Service URL or searchPortal() result dict.

  • viz_params (dict, optional) – Visualization parameters forwarded to the typed helper.

  • name (str, optional) – Layer name.

  • token (str, optional) – ArcGIS token.

  • max_features (int, optional) – Forwarded to addEsriFeatureService().

  • where (str, optional) – SQL WHERE clause forwarded to addEsriFeatureService().

Raises:

ValueError – If the service type cannot be determined.

Example:

import geeViz.esriLib as el

results = el.searchPortal("naip 2023", limit=5)
for r in results:
    el.addEsriService(r)  # dispatches by type automatically