AddressKit is an open-source, scalable address ingestion, validation, search, and autocomplete engine that handles complex address structures for address validation of Australian addresses against the Geocoded National Address File (referred to as G-NAF) — Australia's authoritative address file.
This project is a fork of Addressr, with the objective of improving the quality, performance, and maintainability of the codebase. AddressKit is a rewrite of Addressr in TypeScript with numerous improvements, and is a major improvement over the original project, which is sparsely maintained and contains dangerously outdated dependencies.
It is available as a self-hosted solution, or can be accessed for free through the AddressKit REST API.
AddressKit is actively maintained and developed by Bradley Hodges and is not affiliated with Addressr or its author, Mountain Pass.
Addressr (the library which AddressKit was forked from) is licensed under the Apache 2.0, which expressly permits commercial use, modification, distribution, and sublicensing. You can read more about Apache 2.0 license terms here.
AddressKit is licensed under the GNU GPLv2 license. You can read more about the GNU GPLv2 license here.
AddressKit is a comprehensive solution for managing and validating Australian addresses. Notable features include:
- âś… Autocomplete: Blazingly fast search and autocomplete of Australian addresses based on partial input with result paging, sorting, and filtering
- âś… Locality Search: Dedicated suburb/postcode autocomplete for when you only need locality lookups without full address results
- âś… Canonical validation: Validation is built into AddressKit's core data model since every address is resolved from the G-NAF by default, so "valid" automatically means "authoritatively correct"
- âś… Always up-to-date: AddressKit automatically refreshes its data from the G-NAF every 3 months
- âś… Real-time address validation: Address validation and autocomplete for Australian addresses
- âś… JSON:API compliant: RESTful API conforming to the JSON:API v1.1 specification for standardized, predictable responses
- âś… Easy to use API: Straightforward REST API and CLI service for building your own address validation and autocomplete solutions
- âś… Beautiful CLI: Modern command-line interface with colorful output, progress indicators, and intuitive commands
- âś… Run on your own infrastructure or use ours: Self-host or use our hosted solution
- âś… Completely free and open-source: Completely free or pay for support
- âś… Geocoding: Geocoding of addresses to latitude and longitude coordinates
- âś… Cross-platform: Works on Windows, macOS, and Linux
- Installation
- Enabling Geocoding
- Updating AddressKit
- CLI Reference
- Environment Variables
- API Endpoints
- System Requirements
If you prefer to self-host AddressKit, you have two options for installation: using Docker Compose (recommended), or globally using npm.
The fastest way to get AddressKit running. No installation required - just good ol' Docker.
services:
opensearch:
image: opensearchproject/opensearch:1.3.20
environment:
- discovery.type=single-node
- plugins.security.disabled=true
- OPENSEARCH_JAVA_OPTS=-Xms1g -Xmx1g
ports:
- "9200:9200"
volumes:
- opensearch-data:/usr/share/opensearch/data
healthcheck:
test: ["CMD-SHELL", "curl -fsS http://localhost:9200/_cluster/health >/dev/null || exit 1"]
interval: 10s
timeout: 10s
retries: 30
start_period: 60s
restart: unless-stopped
api:
image: bradleyhodges/addresskit:latest
environment:
- ELASTIC_HOST=opensearch
- ELASTIC_PORT=9200
- PORT=7234
ports:
- "7234:7234"
depends_on:
opensearch:
condition: service_healthy
command: ["addresskit", "start", "--daemon"]
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "curl -fsS http://localhost:7234/addresses?q=test >/dev/null || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
loader:
image: bradleyhodges/addresskit:latest
profiles:
- loader
environment:
- ELASTIC_HOST=opensearch
- ELASTIC_PORT=9200
- COVERED_STATES=${COVERED_STATES:-}
# CRITICAL: Set Node.js heap size for large states (NSW needs 3GB+)
# Set to ~75% of your container memory limit
- NODE_OPTIONS=--max-old-space-size=${LOADER_NODE_HEAP_MB:-3072}
# - ADDRESSKIT_ENABLE_GEO=true # Uncomment to enable geocoding
volumes:
- gnaf-data:/home/node/gnaf
depends_on:
opensearch:
condition: service_healthy
command: ["addresskit", "load"]
restart: "no"
# Increase memory limit for large states (NSW requires 4GB+)
deploy:
resources:
limits:
memory: ${LOADER_MEMORY_LIMIT:-4g}
# Optional: OpenSearch Dashboards for monitoring
dashboards:
image: opensearchproject/opensearch-dashboards:1.3.20
profiles:
- monitoring
environment:
- OPENSEARCH_HOSTS=["http://opensearch:9200"]
- DISABLE_SECURITY_DASHBOARDS_PLUGIN=true
ports:
- "5601:5601"
depends_on:
opensearch:
condition: service_healthy
restart: unless-stopped
volumes:
opensearch-data:
gnaf-data:docker compose up -ddocker compose --profile loader run --rm loaderTip
By default, only ACT is loaded for quick testing. To load specific states, set the COVERED_STATES environment variable:
COVERED_STATES=NSW,VIC,QLD docker compose --profile loader run --rm loaderOr to load all states (takes longer, requires more disk space):
COVERED_STATES= docker compose --profile loader run --rm loader# Search for addresses (autocomplete)
curl -H "Accept: application/vnd.api+json" \
"http://localhost:7234/addresses?q=LEVEL+25,+TOWER+3"
# Get detailed information for a specific address
curl -H "Accept: application/vnd.api+json" \
"http://localhost:7234/addresses/GAVIC411711441"The API returns JSON:API compliant responses. See API Endpoints for detailed examples.
docker compose --profile monitoring up -dAccess the OpenSearch Dashboards at http://localhost:5601 to monitor your index and search performance.
| Service | Description | Default Port | Profile |
|---|---|---|---|
opensearch |
Search backend | 9200 | default |
api |
REST API server | 7234 | default |
loader |
G-NAF data loader | - | loader |
dashboards |
OpenSearch Dashboards | 5601 | monitoring |
For production deployments or advanced configuration, create a .env file alongside your docker-compose.yml:
# States to load (comma-separated: ACT,NSW,VIC,QLD,SA,WA,TAS,NT)
COVERED_STATES=NSW,VIC
# Enable geocoding (latitude/longitude)
ADDRESSKIT_ENABLE_GEO=true
# OpenSearch memory (adjust based on available RAM)
OPENSEARCH_HEAP=2g
# API server port
API_PORT=7234
# CORS origin (set to your domain in production)
CORS_ORIGIN=https://example.comSee Environment Variables for all available options.
node --versionnpm install -g @bradleyhodges/addresskitAfter installation, the addresskit command will be available globally in your terminal. Verify the installation by running:
addresskit --version3. AddressKit requires OpenSearch as its search and indexing backend. If you don't already have an OpenSearch instance running, start one with Docker:
docker run -d --name opensearch \
-p 9200:9200 -p 9300:9300 \
-e "discovery.type=single-node" \
-e "plugins.security.disabled=true" \
-e "OPENSEARCH_JAVA_OPTS=-Xms1g -Xmx1g" \
opensearchproject/opensearch:1.3.204. Configure AddressKit by creating a .env file in the root of your project and adding the following variables (see below for all supported environment variables):
ELASTIC_HOST=opensearch
ELASTIC_PORT=9200
ELASTIC_PROTOCOL=http
ADDRESSKIT_ENABLE_GEO=0 # disable geocoding support (requires more memory) by defaultaddresskit startaddresskit loadNote
If you are using AddressKit for the first time, you will need to load the G-NAF address data into the search index. This will take a while, depending on the size of the G-NAF dataset. Read more about the load command here.
Geocoding is an optional feature that can be enabled by setting the ADDRESSKIT_ENABLE_GEO environment variable to true. This will enable geocoding of addresses to latitude and longitude coordinates. Note that geocoding requires significantly more memory, and is disabled by default.
Add to your .env file:
ADDRESSKIT_ENABLE_GEO=true
# Memory settings for geocoding (adjust based on your server RAM)
# For 16GB server:
LOADER_MEMORY_LIMIT=6g
LOADER_NODE_HEAP_MB=4608
OPENSEARCH_HEAP=6gADDRESSKIT_ENABLE_GEO=1
NODE_OPTIONS=--max-old-space-size=4608[!IMPORTANT] Geocoding requires significantly more memory With geocoding enabled, indexing takes longer and requires approximately 50% more memory. See the Memory by State table for specific requirements. NSW with geocoding requires at least 6GB of Node.js heap.
AddressKit is updated regularly to fix bugs and add new features. You can update AddressKit by pulling the latest Docker image:
docker pull bradleyhodges/addresskit:latestOr, if you are using npm, by running:
npm install -g @bradleyhodges/addresskitIn addition to keeping AddressKit updated, you should regularly update the G-NAF address data to ensure you have the latest addresses. Updates to the G-NAF data are released every 3 months. To automate this chore, you could set up a cron job to keep AddressKit updated. For example, in Linux/macOS, you could add the following to your crontab:
# Run on the 1st of every month at 3am
0 3 1 * * addresskit load --clear # Note: passing the --clear flag will clear the index before loading the latest data, which may cause some downtime. Use with caution.AddressKit provides a beautiful, intuitive command-line interface for managing your address validation service.
___ __ __ __ __ _ __
/ | ____/ /___/ /_______ __________/ //_/(_) /_
/ /| |/ __ / __ / ___/ _ \/ ___/ ___/ ,< / / __/
/ ___ / /_/ / /_/ / / / __(__ |__ ) /| |/ / /_
/_/ |_\__,_/\__,_/_/ \___/____/____/_/ |_/_/\__/
─────────────────────────────────────────────────────
Australian Address Validation & Autocomplete Engine
─────────────────────────────────────────────────────
Usage: addresskit [options] [command]
Options:
-v, --version Display version information
-h, --help Display help information
Commands:
load [options] Load G-NAF address data into the search index
start [options] Start the REST API server
version Display detailed version and environment information
help [command] Display help for a specific command
| Command | Description |
|---|---|
addresskit load |
Download and index G-NAF address data into OpenSearch |
addresskit start |
Start the REST API server |
addresskit version |
Display version and environment information |
addresskit help |
Display help information |
Downloads the latest G-NAF dataset from data.gov.au, extracts it, and indexes all addresses into your OpenSearch instance.
addresskit load [options]Options:
| Option | Description | Default |
|---|---|---|
-d, --daemon |
Run in background mode (suppresses terminal output) | false |
-s, --states <states> |
Comma-separated list of states to load (e.g., NSW,VIC,QLD) |
All states |
--clear |
Clear existing index before loading | false |
--geo |
Enable geocoding support | false |
-h, --help |
Display help for the load command |
Examples:
# Load all states
addresskit load
# Load only NSW and VIC
addresskit load --states NSW,VIC
# Load with geocoding enabled
addresskit load --geo
# Clear index and reload specific states with geocoding
addresskit load --clear --states QLD,SA --geo
# Run in daemon mode (background, no output)
addresskit load -dValid State Codes:
| Code | State |
|---|---|
ACT |
Australian Capital Territory |
NSW |
New South Wales |
NT |
Northern Territory |
OT |
Other Territories |
QLD |
Queensland |
SA |
South Australia |
TAS |
Tasmania |
VIC |
Victoria |
WA |
Western Australia |
Starts the REST API server for address search and validation.
addresskit start [options]Options:
| Option | Description | Default |
|---|---|---|
-d, --daemon |
Run in background mode (suppresses terminal output) | false |
-p, --port <port> |
Port to listen on | 7234 or $PORT |
-h, --help |
Display help for the start command |
Examples:
# Start server on default port (7234)
addresskit start
# Start server on custom port
addresskit start --port 3000
# Start in daemon mode
addresskit start -d
# Start on custom port in daemon mode
addresskit start -d -p 9000Displays detailed version and environment information.
addresskit version| Environment Variable | Description | Default |
|---|---|---|
ELASTIC_HOST |
OpenSearch host | localhost |
ELASTIC_PORT |
OpenSearch port | 9200 |
ELASTIC_PROTOCOL |
Protocol (http or https) |
http |
ELASTIC_USERNAME |
OpenSearch username (optional) | |
ELASTIC_PASSWORD |
OpenSearch password (optional) | |
PORT |
API server port | 7234 |
ES_INDEX_NAME |
OpenSearch index name for addresses | addresskit |
ES_LOCALITY_INDEX_NAME |
OpenSearch index name for localities | addresskit-localities |
NODE_ENV |
Environment (production or development) |
production |
| Environment Variable | Description | Default |
|---|---|---|
COVERED_STATES |
Comma-separated list of states to load (ACT,NSW,VIC,QLD,SA,WA,TAS,NT) | All states |
ADDRESSKIT_ENABLE_GEO |
Enable geocoding (true or 1 to enable) |
Disabled |
ES_CLEAR_INDEX |
Clear index before loading | false |
GNAF_DIR |
Directory for G-NAF data cache | /home/node/gnaf |
| Environment Variable | Description | Default |
|---|---|---|
LOADER_MEMORY_LIMIT |
Container memory limit for loader | 4g |
LOADER_MEMORY_RESERVATION |
Container memory reservation | 2g |
LOADER_NODE_HEAP_MB |
Node.js heap size in MB (~75% of container limit) | 3072 |
OPENSEARCH_HEAP |
OpenSearch JVM heap size | 1g |
OPENSEARCH_MEMORY_LIMIT |
OpenSearch container memory limit | 2g |
Important
LOADER_NODE_HEAP_MB is critical for processing large states. Node.js does not automatically use container memory - you must explicitly set the heap size. For a 4GB container, use 3072 (3GB). For 6GB, use 4608 (4.5GB).
| Environment Variable | Description | Default |
|---|---|---|
PAGE_SIZE |
Default results per page | 8 |
ADDRESSKIT_CACHE_ENABLED |
Enable response caching | true |
ADDRESSKIT_CACHE_MAX_ENTRIES |
Maximum cached entries | 1000 |
ADDRESSKIT_CACHE_TTL_MS |
Cache TTL in milliseconds | 300000 (5 min) |
ADDRESSKIT_DYNAMIC_RESOURCES |
Enable dynamic resource management | true |
ADDRESSKIT_TARGET_MEMORY_UTILIZATION |
Target memory usage ratio | 0.7 |
| Environment Variable | Description | Default |
|---|---|---|
ADDRESSKIT_ACCESS_CONTROL_ALLOW_ORIGIN |
CORS allowed origin | * |
ADDRESSKIT_ACCESS_CONTROL_EXPOSE_HEADERS |
CORS exposed headers | |
ADDRESSKIT_ACCESS_CONTROL_ALLOW_HEADERS |
CORS allowed headers |
| Environment Variable | Description | Default |
|---|---|---|
ADDRESSKIT_INDEX_TIMEOUT |
Index operation timeout | 300s |
ADDRESSKIT_INDEX_BACKOFF |
Initial backoff delay (ms) | 30000 |
ADDRESSKIT_INDEX_BACKOFF_INCREMENT |
Backoff increment (ms) | 30000 |
ADDRESSKIT_INDEX_BACKOFF_MAX |
Maximum backoff delay (ms) | 600000 |
ADDRESSKIT_INDEX_MAX_RETRIES |
Maximum retry attempts | 10 |
| Environment Variable | Description | Default |
|---|---|---|
ADDRESSKIT_STARTUP_MAX_RETRIES |
Max retries waiting for OpenSearch | 60 |
ADDRESSKIT_STARTUP_RETRY_INTERVAL |
Seconds between retries | 5 |
ADDRESSKIT_SKIP_OPENSEARCH_WAIT |
Skip waiting for OpenSearch | false |
ADDRESSKIT_QUIET |
Suppress startup banner | false |
Note: When adjusting
PAGE_SIZE, consider how quickly you want initial results returned. For most use cases, leave it at 8 and use pagination for additional results. Why 8? Mechanical Sympathy.
The AddressKit API conforms to the JSON:API v1.1 specification. All responses use the application/vnd.api+json media type.
| Endpoint | Method | Description |
|---|---|---|
/addresses?q=<query> |
GET | Search for addresses (autocomplete) |
/addresses?q=<query>&page[number]=<n> |
GET | Search with pagination |
/addresses/:id |
GET | Get detailed information for a specific address |
/localities?q=<query> |
GET | Search for localities/suburbs (autocomplete) |
/localities?q=<query>&page[number]=<n> |
GET | Search localities with pagination |
/localities/:id |
GET | Get detailed information for a specific locality |
/docs |
GET | OpenAPI/Swagger documentation |
Search for addresses matching a query string. Returns lightweight autocomplete suggestions optimized for typeahead UX.
Request:
curl -H "Accept: application/vnd.api+json" \
"http://localhost:7234/addresses?q=300+barangaroo"Response:
{
"jsonapi": {
"version": "1.1"
},
"data": [
{
"type": "address-suggestion",
"id": "GANSW716635811",
"attributes": {
"sla": "LEVEL 25, TOWER 3, 300 BARANGAROO AV, BARANGAROO NSW 2000",
"rank": 1
},
"links": {
"self": "/addresses/GANSW716635811"
}
},
{
"type": "address-suggestion",
"id": "GANSW716635812",
"attributes": {
"sla": "LEVEL 26, TOWER 3, 300 BARANGAROO AV, BARANGAROO NSW 2000",
"rank": 0.92
},
"links": {
"self": "/addresses/GANSW716635812"
}
}
],
"links": {
"self": "/addresses?q=300+barangaroo",
"first": "/addresses?q=300+barangaroo",
"prev": null,
"next": "/addresses?q=300+barangaroo&page[number]=2",
"last": "/addresses?q=300+barangaroo&page[number]=5"
},
"meta": {
"total": 42,
"page": 1,
"pageSize": 10,
"totalPages": 5
}
}Retrieve comprehensive details for a specific address by its G-NAF Persistent Identifier (PID). Use this endpoint after a user selects an address from the autocomplete results.
Request:
curl -H "Accept: application/vnd.api+json" \
"http://localhost:7234/addresses/GANSW716635811"Response:
{
"jsonapi": {
"version": "1.1"
},
"data": {
"type": "address",
"id": "GANSW716635811",
"attributes": {
"pid": "GANSW716635811",
"sla": "LEVEL 25, TOWER 3, 300 BARANGAROO AV, BARANGAROO NSW 2000",
"ssla": "25/300 BARANGAROO AV, BARANGAROO NSW 2000",
"mla": [
"LEVEL 25",
"TOWER 3",
"300 BARANGAROO AV",
"BARANGAROO NSW 2000"
],
"structured": {
"buildingName": "Tower 3",
"level": {
"type": { "name": "Level", "code": "L" },
"number": 25
},
"number": {
"number": 300
},
"street": {
"name": "Barangaroo",
"type": { "name": "Avenue", "code": "AV" }
},
"locality": {
"name": "Barangaroo",
"class": { "code": "G", "name": "GAZETTED LOCALITY" }
},
"state": {
"name": "New South Wales",
"abbreviation": "NSW"
},
"postcode": "2000",
"confidence": 2
},
"geo": {
"level": {
"code": 7,
"name": "LOCALITY, STREET, ADDRESS"
},
"geocodes": [
{
"latitude": -33.8535,
"longitude": 151.2012,
"isDefault": true,
"reliability": {
"code": 2,
"name": "WITHIN ADDRESS SITE BOUNDARY OR ACCESS POINT"
},
"type": {
"code": 2,
"name": "PROPERTY CENTROID"
}
}
]
}
},
"links": {
"self": "/addresses/GANSW716635811"
}
},
"links": {
"self": "/addresses/GANSW716635811"
}
}Search for localities (suburbs/postcodes) matching a query string. Returns lightweight autocomplete suggestions - useful when you only need suburb/postcode lookups without full address autocomplete.
Request:
curl -H "Accept: application/vnd.api+json" \
"http://localhost:7234/localities?q=sydney"Response:
{
"jsonapi": {
"version": "1.1"
},
"data": [
{
"type": "locality-suggestion",
"id": "NSW1234",
"attributes": {
"display": "SYDNEY NSW 2000",
"rank": 1
},
"links": {
"self": "/localities/NSW1234"
}
},
{
"type": "locality-suggestion",
"id": "NSW5678",
"attributes": {
"display": "SYDNEY SOUTH NSW 2000",
"rank": 0.85
},
"links": {
"self": "/localities/NSW5678"
}
}
],
"links": {
"self": "/localities?q=sydney",
"first": "/localities?q=sydney",
"prev": null,
"next": "/localities?q=sydney&page[number]=2",
"last": "/localities?q=sydney&page[number]=5"
},
"meta": {
"total": 42,
"page": 1,
"pageSize": 10,
"totalPages": 5
}
}Retrieve comprehensive details for a specific locality by its G-NAF Locality Persistent Identifier (PID). Use this endpoint after a user selects a locality from the autocomplete results.
Request:
curl -H "Accept: application/vnd.api+json" \
"http://localhost:7234/localities/NSW1234"Response:
{
"jsonapi": {
"version": "1.1"
},
"data": {
"type": "locality",
"id": "NSW1234",
"attributes": {
"localityPid": "NSW1234",
"name": "SYDNEY",
"display": "SYDNEY NSW 2000",
"class": {
"code": "G",
"name": "GAZETTED LOCALITY"
},
"state": {
"name": "New South Wales",
"abbreviation": "NSW"
},
"postcode": "2000",
"postcodes": ["2000", "2001"]
},
"links": {
"self": "/localities/NSW1234"
}
},
"links": {
"self": "/localities/NSW1234"
}
}All error responses follow the JSON:API error format:
{
"jsonapi": {
"version": "1.1"
},
"errors": [
{
"status": "404",
"code": "RESOURCE_NOT_FOUND",
"title": "Not Found",
"detail": "The address with ID 'INVALID_123' does not exist."
}
]
}| Status | Description |
|---|---|
400 |
Bad Request - Invalid query parameters |
404 |
Not Found - Address ID does not exist |
500 |
Internal Server Error - Unexpected error |
503 |
Service Unavailable - OpenSearch unavailable |
504 |
Gateway Timeout - Query timeout |
AddressKit is designed to be lightweight and efficient. It is built to run on modest hardware, and is designed to be self-hosted on your own infrastructure.
| Server RAM | OpenSearch Heap | Loader Container | Loader Node Heap | Recommended For |
|---|---|---|---|---|
| 4GB | 1.5GB | 2GB | 1536MB | ACT/TAS/NT only |
| 8GB | 3GB | 4GB | 3072MB | 1-3 states |
| 16GB | 6GB | 6GB | 4608MB | All states |
| 32GB+ | 12GB | 8GB | 6144MB | All states + geocoding |
| State | Addresses | Loader Memory (no geo) | Loader Memory (with geo) |
|---|---|---|---|
| ACT | 280K | 1GB | 1.5GB |
| TAS | 350K | 1GB | 1.5GB |
| NT | 130K | 1GB | 1.5GB |
| SA | 1.1M | 2GB | 3GB |
| WA | 1.3M | 2GB | 3GB |
| QLD | 2.5M | 3GB | 4GB |
| VIC | 3.5M | 3GB | 4.5GB |
| NSW | 4.5M | 4GB | 6GB |
Important
Node.js does not automatically use all container memory. You must explicitly set NODE_OPTIONS=--max-old-space-size=<MB> to increase the heap size. Set it to ~75% of your loader container memory limit. Without this, Node.js defaults to ~1.5GB heap regardless of container size, causing "JavaScript heap out of memory" errors when processing large states.
| Deployment Size | States | Memory | Disk | Use Case |
|---|---|---|---|---|
| Small | 1-2 states (e.g., ACT) | 4GB | 10GB | Development, testing |
| Medium | 3-4 states | 8GB | 30GB | Regional applications |
| Large | All states | 16GB+ | 100GB+ | National production |
Note
If you enable geocoding (ADDRESSKIT_ENABLE_GEO=true), increase memory requirements by approximately 50%. For all states with geocoding, we recommend 32GB+ RAM.
For production deployments, consider:
- Security: Set
CORS_ORIGINto your specific domain(s), enable OpenSearch security, use HTTPS via a reverse proxy - Performance: Tune
OPENSEARCH_HEAPto 50% of available container memory (max 32GB) - Reliability: Set up volume backups for
opensearch-dataandgnaf-data, configure log aggregation - Monitoring: Enable the
monitoringprofile to access OpenSearch Dashboards
- Windows 10/11 (x64)
- macOS 12+ (Intel and Apple Silicon)
- Linux (x64, arm64)
- Ubuntu 20.04+
- Debian 11+
- CentOS 8+
- Amazon Linux 2+
