The PDF guide includes additional details, diagrams, and examples not covered on this page.🔗 Download OpenAPI Spec
Import into Postman, Swagger UI, or any OpenAPI-compatible tool.
Unlike competitors with weekly updates, our Sex Offender Registry API features real-time updates, sub-200ms response times, and an exclusive 99.9% Uptime SLA, making it the reliable choice for background checks, security platforms, and public safety applications.
Base URL
Authentication
Pass your API key as a query parameter key on every request.
Get a free API key at offenders.io/pricing. First 50 requests/month are free.
💡 Using an AI assistant? You can also access full records via our MCP server with the same API key — no code needed.
Search Modes
Regular Search
Targeted lookups by name, DOB, address, zip code, or any combination. At least one query param is required.
Extensive Mode +$0.05/call
Add &mode=extensive to unlock the full depth of our data. Extensive mode searches across all known aliases, cross-references the national registry with state-level sources, and returns enriched response fields:
- aliases — searches all known names and aliases on file
- locations — full address history including residential, employment, and secondary addresses
- stateData — state-specific registry details including offenses, vehicles, registration status, and more (70+ fields across all 50 states)
⚠ Slower response (~2s+). Has rate limit — not for batch processing.
GIS / Geospatial Search EXCLUSIVE
Find offenders within a radius of any GPS coordinate. The only API with native geospatial search. Can combine with name/city filters.
Fuzzy Matching FREE DURING BETA +$0.02/call after beta
Add &fuzzy=true to any search to enable typo-tolerant matching. Works with or without mode=extensive. Fuzzy matching runs on a dedicated search cluster separate from the primary API, providing additional geo-redundancy and infrastructure redundancy — your searches stay fast and available even during maintenance or regional outages. There are two ways to use fuzzy search:
Structured Search (firstName + lastName)
Best when you have separate first and last name fields. Both firstName and lastName are required to activate fuzzy matching — single-name queries fall back to exact matching. Each name is matched independently against the correct field, giving more precise results. Also works with GIS radius search.
Free-Text Search (q)
Best when you have a single combined name string, or want to search across names and addresses together. Searches across first name, last name, aliases, address, city, and zip code in one query.
What Fuzzy Matching Handles
- Misspellings —
SmythmatchesSmith,JonhmatchesJohn - Partial names —
JonmatchesJonathan,RobmatchesRobert - Hyphenated names —
SMITH JOHNSONmatchesSMITH-JOHNSON, and vice versa - Nicknames —
Bobmatches records withRobertin the nickname index - Aliases — matches against all known aliases on file
- Address abbreviations —
DrmatchesDrive,StmatchesStreet,AvematchesAvenue, and other common abbreviations
Query Parameters
| Parameter | Type | Description | Example |
|---|---|---|---|
key | string | Your API key (required) | YOUR_API_KEY |
firstName | string | First name of offender | Alice |
lastName | string | Last name of offender | Smith |
dob | string | Date of birth | 1990-01-15 |
city | string | Residence city | San Francisco |
state | string | Residence state (full name) | California |
zipcode | string | Residence zip code | 94104 |
lat | number | Latitude (GIS search) | 30.967 |
lng | number | Longitude (GIS search) | -91.116 |
radius | number | Radius in miles (default 1, max 100) | 5 |
mode | string | Set to extensive for alias search | extensive |
fuzzy | boolean | Enable typo-tolerant fuzzy matching (+$0.02/call). Works with or without mode=extensive. | true |
q | string | Free-text search across names, aliases, address, city, and zip code. Use with fuzzy=true instead of firstName/lastName. | John Smith San Francisco |
prefixMatch | string | Prefix match on firstName or lastName | firstName |
createdAtStart | string | Filter by when the registrant first appeared in our system. Use this to create alerts for new offenders (e.g., new registrants in a zip code this month). | 2026-01-01 |
createdAtEnd | string | Filter by first appearance in system | 2026-01-31 |
updatedAtStart | string | Filter by last update in system | 2026-01-01 |
updatedAtEnd | string | Filter by last update in system | 2026-01-31 |
faceId | string | Face ID from Facial Search API | 4d8ade05... |
uuid | string | Pull single record by UUID | 807ff46d... |
personUuid | string | Pull single record by Person UUID | 83425e56... |
page | number | Page number for GIS search pagination. Each page is billed as a separate API call. | 3 |
Response Fields
Each offender object in the offenders array contains:
| Field | Type | Description | Example | Empty |
|---|---|---|---|---|
name | string | Full name including middle name | "JOHN M DOE" | "" |
firstName | string | First name | "JOHN" | "" |
lastName | string | Last name | "DOE" | "" |
aliases | array | Known aliases (Extensive Mode only) | [{"givenName":"JAY","surName":"DOE"}] | [] |
dob | ISO date | Date of birth in UTC. Some states report year only (defaults to YYYY-01-01) | "1990-01-15T00:00:00.000Z" | null |
address | string | Residence street address | "123 MAIN ST" | "" |
city | string | Residence city | "RICHMOND" | "" |
state | string | Residence state (full name) | "Virginia" | "" |
zipcode | string | Residence zip code | "23219" | "" |
locations | array | All official addresses (Extensive Mode only) | see Location Object | [] |
sex | string | Registered sex | "Male" | "" |
age | string | Age | "35" | "" |
eyeColor | string | Eye color | "Brown" | "" |
hairColor | string | Hair color | "Black" | "" |
height | string | Height | "5 ft 10 in" | "" |
weight | string | Weight | "180 lbs." | "" |
race | string | Race | "White" | "" |
ethnicity | string | Ethnicity | "Non-Hispanic" | "" |
marks | string | Marks, tattoos, scars | "TAT R ARM, SC L KNEE" | "" |
riskLevel | string | Risk level | "Tier 3" | "" |
crime | string | Crimes committed for registration | "SEXUAL ASSAULT (01/15/2005)" | "" |
registrationDate | ISO date | Date first registered | "2005-03-01T00:00:00.000Z" | null |
offenderUrl | string | URL to source state agency page | "https://example.gov/offender/123" | null |
offenderImageUrl | string | Profile image URL | "https://example.gov/photo/123" | null |
lat | number | Latitude of address | 37.5407 | -1 |
lng | number | Longitude of address | -77.4360 | -1 |
jurisdiction | string | Jurisdiction code (e.g. CA, WV) | "VA" | null |
isAbsconder | boolean | Known absconder status | false | null |
updatedAt | ISO date | Last update timestamp | "2026-03-31T12:00:00.000Z" | null |
uuid | string | Unique record identifier | "807ff46d-1234-5678-9abc-def012345678" | "" |
content | string | Pre-formatted HTML summary | "" | |
sources | array | Data source references | [{"id":"nsopw","name":"NSOPW"}] | [] |
page | number | Current page (GIS only) | 1 | 1 |
totalPages | number | Total pages (GIS only) | 3 | 1 |
stateData* | object | Raw state agency data (Extensive Mode only, experimental) | see stateData Schema | null |
* Experimental fields are not guaranteed and may be removed without notice.
stateData Schema
The stateData object contains structured, state-specific data. Availability varies by state — not all fields are present for every offender.
| Field | Type | Description | Example |
|---|---|---|---|
stateOffenderId | string | State registry ID | "SO-123456" |
status | string | Registration status | "Active", "Incarcerated" |
designation | string | Offender classification | "Sexually Violent Offender" |
complianceStatus | string | Registration compliance | "COMPLIANT", "NON-COMPLIANT" |
offenses | array | Criminal convictions (see Offense Object below) | see below |
aliases | array | Known aliases | ["JOHN DOE", "J DOE"] |
locations | array | Official addresses (see Location Object below) | see below |
vehicles | array | Registered vehicles | [{"plate":"ABC1234","make":"Toyota","model":"Camry","year":"2015","color":"White"}] |
victimInfo | array | Victim information | [{"gender":"Female","minor":true}] |
initialRegistrationDate | string | First registration date | "2000-12-19" |
registrationEnds | string | Registration end date | "2030-12-31" |
isLifetimeRegistration | boolean | Lifetime registration flag | true |
lastVerificationDate | string | Last verification date | "2025-02-20" |
addressVerificationDate | string | Last address verification | "2025-02-20" |
marks | string | Scars, marks, tattoos | "TAT R ARM, SC L KNEE" |
ethnicity | string | Ethnicity | "Hispanic", "Non-Hispanic" |
lawAgency | string | Supervising law enforcement | "HOUSTON POLICE DEPT" |
incarcerationStatus | string | Incarceration/supervision status | "On Parole" |
verificationRequirement | string | Verification frequency | "QUARTERLY" |
employer | string | Employer information | "ACME CORP, CHARLESTON WV" |
school | string | School attendance | "STATE UNIVERSITY" |
Offense Object
| Field | Type | Example |
|---|---|---|
offense | string | "LEWD,LASCIVIOUS CHILD U/16" |
convictionDate | string | "07/02/1998" |
statute | string | "F.S. 800.04" |
victimAge | string | "16" |
victimSex | string | "Female" |
jurisdiction | string | "Miami-Dade, FL" |
caseNumber | string | "CR-2024-0001" |
Location Object
| Field | Type | Example |
|---|---|---|
type | string | "RESIDENTIAL", "WORK" |
streetAddress | string | "123 MAIN ST" |
city | string | "RICHMOND" |
state | string | "VA" |
zipCode | string | "23221" |
latitude | number | 40.7128 |
longitude | number | -74.0060 |
* stateData availability varies by state. Not all fields are present for every record.
Full Example Response
//Response { "offenders": [ { "name": "First M Last", "firstName": "First", "firstName_nicknames": ["firsty", "firs", "1st"], "lastName": "Last", "aliases": [ { "prefix": null, "givenName": "FIR", "middleName": null, "surName": "ST", "suffix": null }, { "prefix": null, "givenName": "FIRST", "middleName": "M", "surName": "LA", "suffix": null }, { "prefix": null, "givenName": "FIRST", "middleName": "NONAME", "surName": "LAST", "suffix": null }, { "prefix": null, "givenName": "X", "middleName": null, "surName": "THE X", "suffix": null } ], "dob": "1900-10-01T00:00:00.000Z", "address": "10000 San Francisco Way", "city": "San Francisco", "state": "California", "zipcode": "94104", "locations": [ { "name": null, "type": "R", "streetAddress": "10000 San Francisco Way", "city": "San Francisco", "county": "California", "state": "CA", "zipCode": "94104", "zipCodeExtension": null, "latitude": 50.12345, "longitude": -34.67890 }, { "name": null, "type": "E", "streetAddress": "200 FL DRIVE", "city": "Miami", "county": "Miami-Daide", "state": "FL", "zipCode": "33129", "zipCodeExtension": null, "latitude": 34.67890, "longitude": -50.12345 } ], "sex": "Male", "age": "123", "offenderUrl": "https://meganslaw.ca.gov/OffenderDisplay.aspx?search...", "offenderImageUrl": "https://meganslaw.ca.gov/NSOPWPI.ashx?f=...&NSOPRFlag=True", "jurisdiction": "CA", "isAbsconder": false, "isPredator": true, "eyeColor": "Green", "hairColor": "Brown", "height": "5'11\"", "weight": "200 lbs.", "race": "White", "marks": "tattoo on r_arm (cross / cover the cross with tribal symbol); tattoo on l_arm (pic of a lady); tattoo on l_arm (something); ...", "riskLevel": "2", "crime": "Crime: 14:81 - Indecent Behavior with Juveniles; Juvenile victim, Conviction date: 2199-09-09, Jurisdiction: California", "registrationDate": "2012-12-31T00:00:00.000Z", "content": "<br><b>Zip Code: </b>94104<br><b>Sex: </b>Male<br><b>Age: </b>123...", "lat": 50.12345, "lng": -34.67890, "sources": [ { "name": "National Sex Offender Public Website", "id": "nsopw", "url": "https://www.nsopw.gov/" }, { "name": "New York State Division of Criminal Justice Services", "id": "criminaljustice.ny.gov", "url": "https://www.criminaljustice.ny.gov/" } ], "updatedAt": "2026-03-05T21:35:42.936Z", "uuid": "5893a310-37ce-58d8-b101-39e76a60e94a", "stateData": { "stateOffenderId": "SO-123456", "status": "Active", "designation": "Sexually Violent Offender", "offenses": [ { "offense": "AGGRAVATED SEXUAL BATTERY", "convictionDate": "11/04/1999", "statute": "18.2-67.3", "jurisdiction": "Richmond Circuit", "victimAge": "Unknown" } ], "aliases": ["JOHN A DOE", "JOHNNY DOE"], "initialRegistrationDate": "2000-12-19", "lastVerificationDate": "2026-02-20", "complianceStatus": "COMPLIANT", "isLifetimeRegistration": true, "incarcerationStatus": "On Parole", "lawAgency": "RICHMOND POLICE DEPT", "vehicles": [{"plate":"ABC1234","make":"Toyota","year":"2015"}], "victimInfo": [{"gender":"Female","minor":true}] } } ] }
Result Limits
- Regular Search: 50 records max. Filter by city or zip for better results.
- GIS Search: Radius defaults to 1 mi (max 100 mi). 50 records per page — use
pageandtotalPagesto paginate. Each page request counts as one billable API call. For example, a search returning 5 pages of results consumes 5 API calls. - Fuzzy Search: Up to 2,000 records per request. Requires at least two search parameters (e.g. firstName + lastName).
Higher limits for name searches can be enabled at no extra cost. All results are returned in a single API call. Contact us to enable this for your account.
Error Handling
| Code | Meaning | Example Response |
|---|---|---|
| 400 | Bad Request | {"error":"Invalid input params","reason":"no query params presented"} |
| 401 | Unauthorized — missing or invalid API key | {"code":401,"message":"Missing API key"} |
| 405 | Method Not Allowed |
Code Examples
JavaScript / Node.js
const res = await fetch( `https://api.offenders.io/sexoffender?key=${API_KEY}&zipcode=94104` ) const { offenders } = await res.json() console.log(offenders[0].name, offenders[0].city)
Python
import requests r = requests.get("https://api.offenders.io/sexoffender", params={ "key": API_KEY, "firstName": "Alice", "zipcode": "94104" }) offenders = r.json()["offenders"]
cURL
curl "https://api.offenders.io/sexoffender?key=YOUR_KEY&lat=30.967&lng=-91.116&radius=2"Batch Processing
Need to process thousands of records? Use our web-based batch tool at batch.offenders.io — upload a CSV with First Name, Last Name, and optional DOB. See the Batch Processing Guide for details.
Ready to integrate?
Get your free API key and start making calls in minutes — via REST API or MCP server.
Get Free API Key →