Skip to content

About

A python wrapper for the NYC Geosearch v2 API. A way to get official location information from The City of New York's GeoSupport service's REST API using Python.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

NYC GeoSearch Python Wrapper

A Python client library for the NYC GeoSearch API v2, providing geocoding and autocomplete functionality for New York City addresses using authoritative data from the Property Address Directory (PAD).

Features

  • Simple and intuitive API - Easy-to-use Python interface
  • Both sync and async support - Use with regular requests or async/await
  • Comprehensive geocoding - Search for addresses, landmarks, and places
  • Real-time autocomplete - Fast typeahead suggestions for UIs
  • Geographic filtering - Focus searches by location or boundary
  • Structured responses - Clean data models with type hints
  • Error handling - Proper exception handling with detailed error messages
  • Rate limiting - Built-in respectful rate limiting
  • Session management - Connection pooling and context managers

Installation

pip install nyc-geosearch

# For async support:
pip install nyc-geosearch[async]
# or install aiohttp separately:
pip install aiohttp

Quick Start

from geosearch import GeoSearchClient

# Basic search
with GeoSearchClient() as client:
    result = client.search("120 Broadway, Manhattan")
    if result:
        feature = result[0]
        print(f"Found: {feature.properties.label}")
        print(f"Coordinates: {feature.geometry.coordinates}")

# Autocomplete for UIs
with GeoSearchClient() as client:
    suggestions = client.autocomplete("120 Broad")
    for suggestion in suggestions:
        print(suggestion.properties.label)

API Reference

GeoSearchClient

The main synchronous client for the NYC GeoSearch API.

Constructor

GeoSearchClient(
    base_url: str = "https://geosearch.planninglabs.nyc",
    version: str = "v2", 
    timeout: int = 30,
    session: requests.Session = None
)

Methods

search(text, **kwargs) → GeoSearchResult

Search for addresses and places. Use this for complete addresses or when users paste full addresses.

Parameters:

  • text (str): Address or place name to search for
  • size (int, optional): Number of results (1-40, default: 10)
  • focus_lat, focus_lon (float, optional): Geographic focus point
  • boundary_rect_* (float, optional): Rectangular boundary limits
  • boundary_circle_* (float, optional): Circular boundary limits

Example:

# Basic search
result = client.search("Empire State Building")

# Search with geographic focus
result = client.search(
    "Main Street",
    focus_lat=40.6782,
    focus_lon=-73.9442  # Focus on Brooklyn
)

# Search within boundary
result = client.search(
    "Park Avenue",
    boundary_rect_min_lat=40.700,
    boundary_rect_min_lon=-74.020,
    boundary_rect_max_lat=40.790,
    boundary_rect_max_lon=-73.930
)
autocomplete(text, **kwargs) → GeoSearchResult

Get autocomplete suggestions. Use this for real-time typeahead in UIs.

Parameters:

  • text (str): Partial address or place name
  • focus_lat, focus_lon (float, optional): Geographic focus point
  • boundary_rect_* (float, optional): Rectangular boundary limits

Example:

# Real-time autocomplete
suggestions = client.autocomplete("120 Br")
for suggestion in suggestions[:5]:  # Top 5 suggestions
    print(suggestion.properties.label)

AsyncGeoSearchClient

Async version for concurrent requests.

import asyncio
from geosearch import AsyncGeoSearchClient

async def main():
    async with AsyncGeoSearchClient() as client:
        result = await client.search("Brooklyn Bridge")
        print(result[0].properties.label)

asyncio.run(main())

Data Models

GeoSearchResult

Container for API responses with list-like interface.

result = client.search("Broadway")

# Access features
print(len(result))           # Number of results
print(result[0])            # First feature
for feature in result:      # Iterate features
    print(feature.properties.label)

# Metadata
print(result.geocoding.version)  # API version
print(result.bbox)              # Bounding box

Feature

Individual search result with GeoJSON structure.

feature = result[0]

# Properties (address info)
props = feature.properties
print(props.label)          # Full formatted address
print(props.name)           # Short name
print(props.housenumber)    # House number
print(props.street)         # Street name
print(props.borough)        # NYC borough
print(props.confidence)     # Match confidence score

# Geometry (coordinates)
coords = feature.geometry.coordinates  # [longitude, latitude]
lat, lon = coords[1], coords[0]

Properties

Detailed address information.

Common fields:

  • label - Full formatted address
  • name - Short name/description
  • confidence - Match quality score (0-1)
  • housenumber - House/building number
  • street - Street name
  • borough - NYC borough (Manhattan, Brooklyn, etc.)
  • neighbourhood - Neighborhood name
  • postalcode - ZIP code
  • pad_bin - NYC Building Identification Number
  • pad_bbl - NYC Borough, Block, and Lot number

Advanced Usage

Geographic Focus

Prioritize results near a specific location:

# Focus search around user's location
result = client.search(
    "Coffee Shop",
    focus_lat=40.7589,  # Near Times Square
    focus_lon=-73.9851
)

Boundary Filtering

Limit results to specific geographic areas:

# Search only within Manhattan
result = client.search(
    "Park Avenue",
    boundary_rect_min_lat=40.700,
    boundary_rect_min_lon=-74.020, 
    boundary_rect_max_lat=40.790,
    boundary_rect_max_lon=-73.930
)

# Search within 2km radius
result = client.search(
    "Pizza",
    boundary_circle_lat=40.7589,
    boundary_circle_lon=-73.9851,
    boundary_circle_radius=2.0
)

Concurrent Requests

Use async client for better performance:

import asyncio
from geosearch import AsyncGeoSearchClient

async def geocode_addresses(addresses):
    async with AsyncGeoSearchClient() as client:
        tasks = [client.search(addr) for addr in addresses]
        results = await asyncio.gather(*tasks)
        return results

# Geocode multiple addresses concurrently
addresses = ["120 Broadway", "1 Wall Street", "Times Square"]
results = asyncio.run(geocode_addresses(addresses))

Custom Configuration

import requests
from geosearch import GeoSearchClient

# Custom session with connection pooling
session = requests.Session()
session.headers.update({'User-Agent': 'MyApp/1.0'})

# Custom timeout and session
client = GeoSearchClient(
    timeout=60,
    session=session
)

Error Handling

The library provides specific exceptions for different error types:

from geosearch import (
    GeoSearchClient,
    GeoSearchException,
    GeoSearchAPIException, 
    GeoSearchTimeoutException,
    GeoSearchValidationException
)

with GeoSearchClient() as client:
    try:
        result = client.search("Some address")
    except GeoSearchValidationException as e:
        print(f"Invalid parameters: {e}")
    except GeoSearchTimeoutException as e:
        print(f"Request timed out: {e}")
    except GeoSearchAPIException as e:
        print(f"API error {e.status_code}: {e}")
    except GeoSearchException as e:
        print(f"General error: {e}")

Rate Limiting

The client includes built-in rate limiting to be respectful to the API:

  • Minimum 100ms between requests
  • Automatic throttling
  • Can be customized by subclassing
client = GeoSearchClient()
client._min_request_interval = 0.2  # 200ms between requests

Examples

See the examples/ directory for comprehensive usage examples:

  • basic_usage.py - Common use cases and features
  • async_usage.py - Async/concurrent examples
  • ui_integration.py - Integrating with web UIs
  • batch_geocoding.py - Processing multiple addresses

API Documentation

This wrapper is based on the NYC GeoSearch API v2, which uses the Pelias geocoding engine with NYC-specific data from the Property Address Directory (PAD).

Official API Documentation:

Endpoints:

  • /v2/search - Precise geocoding for complete addresses
  • /v2/autocomplete - Fast autocomplete suggestions

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

License

MIT License - see LICENSE file for details.

Support

Changelog

1.0.0

  • Initial release
  • Sync and async clients
  • Full API coverage
  • Comprehensive error handling
  • Type hints and documentation

About

A python wrapper for the NYC Geosearch v2 API. A way to get official location information from The City of New York's GeoSupport service's REST API using Python.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages