# NZ Address Geocode + Fault Lookup (LINZ/GEM) (`spindux/nz-property-master`) Actor

One call, JSON out. Geocode messy NZ addresses, attach the nearest active fault, run lists in bulk. Linear LINZ geocoding under the hood, GEM fault lookup attached when you ask for it. No glue code, no manual suburb disambiguation, no licence archaeology.

- **URL**: https://apify.com/spindux/nz-property-master.md
- **Developed by:** [Josh Chamberlin](https://apify.com/spindux) (community)
- **Categories:** Real estate, Developer tools
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.10 / 1,000 geocode results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## NZ Property & Address Master

> Geocode messy NZ addresses and bundle property-level context — including nearest active fault — into a single normalised JSON snapshot.

Public-data Actor for the New Zealand property stack. Single call, JSON out, attribution strings included in every result.

### What it does

Three operations:

| Operation | Input | Output |
|-----------|-------|--------|
| `geocode` | messy NZ address string | canonical address + lat/lon + territorial authority + confidence |
| `snapshot` | address or `parcel_id` | geocode + nearest active fault (name, slip type, distance) |
| `bulk` | list of addresses | list of geocodes (fast path, no hazards) |

#### Geocode quality

The geocoder returns a `match_status` so you know what you're getting:

- `exact` — input substring of LINZ canonical (capped confidence 0.99)
- `partial` — leading number match (capped confidence 0.94)
- `fuzzy` — token AND with anchor-gated fallback (capped confidence 0.6)
- `no_match` — refuses rather than confidently returns a wrong address

Conservative on purpose: a "no_match" beat a confidently-wrong Napier coords for "327 Bluff Road, Bluff".

#### Hazards overlay (snapshot only)

For each geocoded property, the Actor computes the haversine distance to the nearest known active fault trace from the **GEM Foundation Global Active Faults Database**. Returns:

- Fault name (e.g. "Wellington-Hutt Valley 4")
- Catalog ID (e.g. `NZ_291`)
- Slip type (e.g. "Dextral-Normal")
- Distance in kilometres
- Full CC BY-SA 4.0 attribution strings (Styron & Pagani 2020, Litchfield et al. 2014 NZ component)

Search radius configurable via `fault_search_km` (default 100 km, max 1000 km). Set `include_hazards: false` to skip the GEM lookup on a hot path.

### Data sources (free + official)

All sources are New Zealand public data with permissive licences:

- **LINZ Data Service** — Street Address dataset (layer 123113), NZ Property Titles (layer 50804). CC BY 4.0, attribution required. LINZ-API key required as Actor secret.
- **GEM Foundation Global Active Faults Database** — GeoJSON download, NZ traces from Litchfield et al. 2014. CC BY-SA 4.0, attribution strings included in every output row.

The Actor does not scrape, does not access paywalled data, does not store customer input.

### Sample request / response

#### Input

```json
{
  "operation": "snapshot",
  "address": "1 Molesworth Street, Wellington, 6011",
  "include_hazards": true,
  "fault_search_km": 100
}
````

#### Output (one row)

```json
{
  "input_address": "1 Molesworth Street, Wellington, 6011",
  "canonical_address": "101 Molesworth Street, Thorndon, Wellington",
  "lat": "-41.2740910167",
  "lon": "174.77771315",
  "match_status": "partial",
  "ta": "Wellington City",
  "region": "Wellington",
  "confidence": "0.73",
  "source": "LINZ",
  "attribution": "Contains data sourced from Land Information New Zealand under Creative Commons Attribution 4.0 International (CC BY 4.0).",
  "nearest_fault_name": "Wellington Hutt Valley 4",
  "nearest_fault_catalog_id": "NZ_291",
  "nearest_fault_slip_type": "Dextral-Normal",
  "nearest_fault_distance_km": "0.057",
  "nearest_fault_source": "GEM Global Active Faults Database (CC BY-SA 4.0)",
  "hazards_attribution_primary": "GEM Foundation Global Active Faults Database (CC BY-SA 4.0), doi:10.1177/8755293020944182",
  "hazards_attribution_nz": "NZ traces: Litchfield et al. 2014, doi:10.1080/00288306.2013.854256"
}
```

### Pricing

Per-result via Apify Pay-Per-Event. Head-on price comparison with Google:

| Operation | This Actor | Google direct | Notes |
|---|---|---|---|
| Single geocode | **$0.0001** / result ($0.10/1k) | Geocoding API: $5/1k. Address Validation: ~$8–10/1k | 50× below Google's direct API; ~7× below OSM-backed alternatives |
| Address + nearest fault + canonical + attribution | **$0.015** / result ($15/1k) | $5 + separate fault lookup = much more | Bundle is the value; one call replaces three |
| Bulk (geocode only) | **$0.0005** / result ($0.50/1k) | Maps Batch Geocoding: $10/1k | Bulk skips hazards for cost reasons |

Subscriptions are not offered yet — Apify is retiring the rental model on **2026-10-01** and Apify Pay-Per-Event is now the only path. Re-evaluate after first paid month.

### Configuration

Required: `LINZ_API_KEY` set as a **secret** environment variable on the Actor. Free at <https://data.linz.govt.nz/>.

The GEM data is downloaded at Actor startup and cached to `/tmp` for 14 days. No second API key required.

### Local dev

```bash
## One-time setup
cd actors/nz-property-master
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"

## Run locally (no Apify infrastructure)
cp .env.example .env  # fill in LINZ_API_KEY
APIFY_LOCAL=true python -m src.main --input '{"address": "1 Molesworth Street, Wellington, 6011"}'
```

### Tests

```bash
source .venv/bin/activate
python -m pytest tests/ -v   # 33/33 passing locally
```

The test suite covers geocoder match classification, anchor extraction, GNS/GEM cache hit/miss expiry, haversine + cross-track distance math, and Pydantic model round-trip.

### Compliance

- Public data only — LINZ (CC BY 4.0) + GEM Global Active Faults Database (CC BY-SA 4.0)
- No PII collected, no third-party scraping, no auth-walled data
- Attribution strings included in every output row
- \~10 requests/sec sustained — bulk jobs throttle automatically

### Changelog

- **0.10.21** — Hazards overlay (GEM Global Active Faults) wired into `snapshot` operation. Attribution strings included. 33/33 pytest passing.
- **0.10.18** — Geocoder fixes: anchor-gated fuzzy, `match_status` field, conservative `no_match`. False-positive regression tests added.
- **0.10.17** — Real LINZ WFS integration, three-strategy matcher.
- **0.10.16** — Phase 1 complete: stub `geocode` + `snapshot` + `bulk` operations.
- **0.11 (planned)** — Listing copy finalised (Variant B / Tier B). Pricing tier locked. Ready for Claude Code review of code + plan.

# Actor input Schema

## `operation` (type: `string`):

What to do: 'geocode' = address → canonical form + metadata, 'snapshot' = address/parcel → full property snapshot (geocode + hazards), 'bulk' = list of addresses → geocoded results.

## `address` (type: `string`):

Free-text NZ address to geocode or snapshot. Required for operations: geocode, snapshot (when not using parcel\_id).

## `parcel_id` (type: `string`):

LINZ parcel identifier. Optional, for operation: snapshot.

## `addresses` (type: `array`):

List of free-text NZ addresses to bulk-geocode. Required for operation: bulk.

## `include_hazards` (type: `boolean`):

Attach nearest active fault (GEM Global Active Faults, CC BY-SA 4.0) to snapshot output.

## `fault_search_km` (type: `integer`):

Search radius for the nearest active fault lookup, in kilometres.

## Actor input object example

```json
{
  "operation": "geocode",
  "include_hazards": true,
  "fault_search_km": 100
}
```

# Actor output Schema

## `input_address` (type: `string`):

No description

## `canonical_address` (type: `string`):

No description

## `lat` (type: `string`):

No description

## `lon` (type: `string`):

No description

## `match_status` (type: `string`):

No description

## `parcel_id` (type: `string`):

No description

## `meshblock` (type: `string`):

No description

## `electorate` (type: `string`):

No description

## `ta` (type: `string`):

No description

## `region` (type: `string`):

No description

## `confidence` (type: `string`):

No description

## `source` (type: `string`):

No description

## `attribution` (type: `string`):

No description

## `nearest_fault_name` (type: `string`):

No description

## `nearest_fault_catalog_id` (type: `string`):

No description

## `nearest_fault_slip_type` (type: `string`):

No description

## `nearest_fault_distance_km` (type: `string`):

No description

## `nearest_fault_source` (type: `string`):

No description

## `hazards_attribution_primary` (type: `string`):

No description

## `hazards_attribution_nz` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("spindux/nz-property-master").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("spindux/nz-property-master").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call spindux/nz-property-master --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=spindux/nz-property-master",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "NZ Address Geocode + Fault Lookup (LINZ/GEM)",
        "description": "One call, JSON out. Geocode messy NZ addresses, attach the nearest active fault, run lists in bulk. Linear LINZ geocoding under the hood, GEM fault lookup attached when you ask for it. No glue code, no manual suburb disambiguation, no licence archaeology.",
        "version": "0.14",
        "x-build-id": "Pf8lGVnTheWUp7IOj"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/spindux~nz-property-master/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-spindux-nz-property-master",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/spindux~nz-property-master/runs": {
            "post": {
                "operationId": "runs-sync-spindux-nz-property-master",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/spindux~nz-property-master/run-sync": {
            "post": {
                "operationId": "run-sync-spindux-nz-property-master",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "operation"
                ],
                "properties": {
                    "operation": {
                        "title": "Operation",
                        "enum": [
                            "geocode",
                            "snapshot",
                            "bulk"
                        ],
                        "type": "string",
                        "description": "What to do: 'geocode' = address → canonical form + metadata, 'snapshot' = address/parcel → full property snapshot (geocode + hazards), 'bulk' = list of addresses → geocoded results.",
                        "default": "geocode"
                    },
                    "address": {
                        "title": "Address",
                        "type": "string",
                        "description": "Free-text NZ address to geocode or snapshot. Required for operations: geocode, snapshot (when not using parcel_id)."
                    },
                    "parcel_id": {
                        "title": "Parcel ID",
                        "type": "string",
                        "description": "LINZ parcel identifier. Optional, for operation: snapshot."
                    },
                    "addresses": {
                        "title": "Addresses (bulk)",
                        "type": "array",
                        "description": "List of free-text NZ addresses to bulk-geocode. Required for operation: bulk.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "include_hazards": {
                        "title": "Include Hazards (snapshot only)",
                        "type": "boolean",
                        "description": "Attach nearest active fault (GEM Global Active Faults, CC BY-SA 4.0) to snapshot output.",
                        "default": true
                    },
                    "fault_search_km": {
                        "title": "Fault Search Radius (km)",
                        "minimum": 1,
                        "maximum": 1000,
                        "type": "integer",
                        "description": "Search radius for the nearest active fault lookup, in kilometres.",
                        "default": 100
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
