---
title: "Python SDK Quick Start, PLSS Coordinate Conversion in Python | Township America"
description: "Install the townshipamerica Python package and convert PLSS legal land descriptions to GPS coordinates in four lines of code. Typed responses, sync and async clients."
url: https://townshipamerica.com/guides/python-sdk
---

# Python SDK Quick Start, PLSS Coordinate Conversion in Python

Install the townshipamerica Python package and convert PLSS legal land descriptions to GPS coordinates in four lines of code. Typed responses, sync and async clients.

Convert PLSS legal land descriptions to GPS coordinates in Python with the official `townshipamerica` package. MIT license, typed Pydantic v2 models, sync and async clients.

## [Installation](#installation)

Install from PyPI with pip:

```
pip install townshipamerica

```

Requires Python 3.9 or later. Dependencies (`httpx`, `pydantic`) install automatically.

## [Your first conversion](#your-first-conversion)

### [Get an API key](#get-an-api-key)

Sign up at [townshipamerica.com/app](https://townshipamerica.com/app) and subscribe to the Search API from the Developer Portal.

### [Set your API key](#set-your-api-key)

Store your key as an environment variable, never hardcode it in source files.

```
export TOWNSHIPAMERICA_API_KEY="your_api_key"

```

### [Convert a PLSS description](#convert-a-plss-description)

```
import os
from townshipamerica import TownshipAmerica

client = TownshipAmerica(api_key=os.environ["TOWNSHIPAMERICA_API_KEY"])
result = client.search("NENE 12 4N 5E Indian Meridian")

feature = result.features[0]
print(feature.properties)           # Section metadata
print(feature.geometry.coordinates) # Boundary polygon

```

That's it, `result` is a typed `FeatureCollection` with GeoJSON geometry and PLSS metadata.

## [Reverse geocoding](#reverse-geocoding)

Find the PLSS legal land description at a GPS coordinate:

```
result = client.reverse(-97.5, 36.1)

feature = result.features[0]
print(feature.properties.descriptor)  # "NWSE 15 4N 7W Indian Meridian"

```

The `unit` parameter controls precision, `"Township"`, `"Section"`, `"Quarter Section"`, or `"all"`:

```
result = client.reverse(-97.5, 36.1, unit="Quarter Section")

```

## [Autocomplete](#autocomplete)

Add type-ahead search for PLSS descriptions:

```
suggestions = client.autocomplete("T4N R5E", limit=5)
for item in suggestions.results:
    print(item.text, item.location)

```

The `proximity` parameter biases results toward a GPS coordinate:

```
suggestions = client.autocomplete(
    "T4N",
    limit=5,
    proximity=(-97.5, 36.1)
)

```

## [Batch conversion](#batch-conversion)

Convert up to 100 PLSS descriptions in a single request:

```
locations = [
    "NENE 12 4N 5E Indian Meridian",
    "NESW 25 5N 30E Mount Diablo Meridian",
    "SWNE 22 3N 7E Montana Meridian",
]

results = client.batch_search(locations)
for fc in results:
    feature = fc.features[0]
    print(feature.properties.descriptor, feature.geometry.coordinates[0][0][:2])

```

Batch reverse geocoding works the same way:

```
coordinates = [(-97.5, 36.1), (-110.0, 45.5), (-104.8, 39.7)]
results = client.batch_reverse(coordinates, unit="Section")

```

## [Error handling](#error-handling)

The SDK raises typed exceptions mapped to HTTP status codes:

```
from townshipamerica.exceptions import (
    AuthenticationError,
    NotFoundError,
    RateLimitError,
    ValidationError,
)

try:
    result = client.search("invalid input")
except ValidationError as e:
    print(f"Bad input: {e}")
except AuthenticationError:
    print("Check your API key")
except RateLimitError as e:
    print(f"Rate limited, retry after {e.retry_after} seconds")
except NotFoundError:
    print("No PLSS data at that location")

```

## [Context manager](#context-manager)

The client supports `with` statements for automatic cleanup:

```
with TownshipAmerica(api_key=os.environ["TOWNSHIPAMERICA_API_KEY"]) as client:
    result = client.search("NENE 12 4N 5E Indian Meridian")
    print(result.features[0].properties)
# Connection closed automatically

```

## [Related guides](#related-guides)

* [Python SDK Async & GeoPandas Patterns](/guides/python-sdk-advanced) \- Async workflows, GeoPandas integration, and production patterns
* [API Integration Guide](/guides/api-integration) \- REST API endpoints, pricing, and integration patterns
* [Batch Conversion](/guides/batch-conversion) \- Web interface for batch processing

Need help? [Contact us](/contact-us).

### Related Guides

[Legal Land Description API Integration GuideIntegrate legal land description APIs into your applications. Convert PLSS descriptions to coordinates, add autocomplete search, process batch records, and display survey grid maps. REST API with JSON responses.](/guides/api-integration)[Google Sheets Add-on, PLSS to GPS Conversion in SpreadsheetsConvert PLSS legal land descriptions to GPS coordinates directly in Google Sheets. Free add-on with 10 conversions/month, unlimited with API key. Batch column conversion, cell formulas, and API key management.](/guides/google-sheets-add-on)[Python SDK Advanced Patterns, Async, GeoPandas, and Production WorkflowsUse the townshipamerica Python SDK with async/await, GeoPandas DataFrames, and production-ready error handling for GIS pipelines and land tech applications.](/guides/python-sdk-advanced)
