Tutorial

Address Autocomplete API for Forms: Cost and Setup

What eight address autocomplete APIs charge, read from each vendor's own page on the same day, what 10,000 form fills a month would cost on each, and the two lines of form code that decide the bill.

Marcus Chen
October 16, 2026 · 10 min read · Last reviewed

An address autocomplete API suggests complete addresses while a person types into a form field, so they pick one instead of typing it all. What it costs depends on how the vendor counts: per request, per session or per lookup. Free tiers we read on October 16, 2026 ranged from none (Radar) to 100,000 requests a month (sthan.io), and calling on every keystroke instead of after a pause can turn one billed request per address into about ten.

Free tiers and prices of address autocomplete APIs

Each row was read from the vendor's own pricing page on October 16, 2026. Vendors count usage differently, so the "Billed per" column matters as much as the price. Geoapify, Mapbox and Radar are map and geocoding platforms; their autocomplete suggests places and addresses from map data.

APIBilled perFreePaid price
sthan.io US Address AutocompleteRequest100,000 requests a month, no credit card$7 a month for 100,000; $48 a month for 1,000,000
Google Places Autocomplete (New)Request, or session10,000 Autocomplete Requests a month$2.83 per 1,000 requests (up to 100,000), lower with volume. Sessions: see below
Smarty US Autocomplete ProLookup (each query)42-day trial, 1,000 lookups, no credit card$21 a month for 5,000; $65 for 25,000; $220 for 125,000
Geoapify Address AutocompleteCredit (1 per request)3,000 credits a day, no credit card$59 a month for 10,000 credits a day
Mapbox Address AutofillSession1,000 sessions a month$12.50 per 1,000 sessions (1,001 to 25,000), lower with volume
Radar Core Maps (includes address autocomplete)API callNone ("Radar does not currently offer a free tier")Starting at $0.50 per 1,000 calls; annual commitment, priced by quote
Loqate Address Capture, US and CanadaLookup45-day free trial5 cents per lookup on the $100 plan; 4.3 cents on the $1,000 plan; credit valid 12 months
PostGrid Address Verification, StandardNot stated for autocomplete500 free credits listed on each planAddress Autocomplete is listed as a feature of the Standard (US and Canada) plans, from $20 a month for 2,000 lookups; the page does not say how autocomplete requests are counted

What "Billed per" means in practice:

  • Per request or lookup (sthan.io, Smarty, Geoapify, Radar): every call counts, so calling less often lowers your bill directly. Smarty puts it plainly: with a query on every keystroke, "entering an address might consume around ten lookups."
  • Per session (Mapbox Address Autofill): you pay once per user session, and "each session may include unlimited Temporary Geocoding API requests."
  • Google, both: without a session token, every Autocomplete (New) request is billed. With a session token, the bill depends on how the session ends (see Google's session section below).

What 10,000 form fills a month would cost

This is our arithmetic from the prices above, for 10,000 completed addresses in one month. The first column is the best case: about one request per address, which our test further down only reached because its typing never paused. The second assumes a request on every keystroke, using Smarty's estimate of about ten per address.

API1 request per address, best case (10,000 requests)10 requests per address (100,000 requests)
sthan.io$0 (inside the 100,000 free)$0 (uses all 100,000 free); $7 Basic plan for headroom
Google, no session token$0 (inside the 10,000 free)$254.70 (90,000 billed at $2.83 per 1,000)
Google, session ends in Place Details Essentials$0 (10,000 requests and 10,000 Place Details calls, both inside the free caps)$254.70 (all 10 requests per session are billed; the 10,000 Place Details calls are free)
Google, session ends in Address Validation$225 (typing free; 9,000 validations at $25 per 1,000)$225 (same; this also checks each address)
Smarty$65 (smallest monthly plan that covers 10,000: 25,000 lookups)$220 (125,000 lookups)
Geoapify$0 (about 333 a day, under 3,000)$59 (about 3,333 a day, over the free 3,000)
Mapbox Address Autofill$112.50 (if one session per address: 9,000 at $12.50 per 1,000)$112.50 (sessions, so keystrokes do not change it)
RadarFrom $5, by quote, annualFrom $50, by quote, annual
Loqate, PostGridNot worked out: their pricing pages do not say what counts as an autocomplete lookup

Three things stand out. For a per-request API, the way your form calls it matters more than the list price: the same 10,000 addresses cost Google $0 or $254.70. Session pricing (Mapbox, and Google ending in Address Validation) makes keystrokes free but charges for every completed address. Google adds up usage across all projects on your billing account each month, so other Places usage changes these numbers. Geoapify's figures assume the same traffic every day of a 30-day month.

Google's session pricing, in plain terms

A Google session starts with the first Autocomplete (New) request that carries a session token and ends with a Place Details (New) or Address Validation request that uses the same token. From Google's session pricing page:

Session ends withAutocomplete requestsEnding request billed at
Place Details Essentials (address and location)First 12 billed as Autocomplete Requests; 13 and later freePlace Details Essentials: $5.00 per 1,000 after 10,000 free (first paid tier, lower above 100,000)
Place Details Essentials (IDs Only)All billed as Autocomplete Requests, as if no sessionNot charged
Address Validation (checkout and delivery)All freeAddress Validation Enterprise: $25.00 per 1,000 after 1,000 free (first paid tier, lower above 100,000)
Nothing (abandoned session)All billed as Autocomplete Requestsn/a

So a checkout that ends each session with Address Validation pays $25 per 1,000 completed addresses after the free 1,000 at the first paid tier (up to 100,000 a month, lower above that), and nothing for the typing. A form that ends with Place Details Essentials pays for up to 12 requests per session plus the details call. People who start typing and leave are billed per request either way.

The setup that keeps the bill low

  1. Wait for a pause. Start a short timer on each keystroke and call only when it runs out. This is called debouncing. We used 300 milliseconds; sthan.io's FAQ suggests 300 to 500.
  2. Go through your server. A route on your server adds the API key, so it never appears in page source, and skips inputs shorter than three characters. sthan.io's docs say "Min 3 chars for best results."
  3. Cancel late answers. When a new keystroke comes in or the person picks a suggestion, cancel the waiting timer and any request still on its way. Otherwise a slow, older answer can replace the current list or reopen it after a choice.
  4. Verify once. People can change the line after picking it, for example to add an apartment number. One verification call on submit returns a status for the final address. See validating addresses at signup and checkout.

Below is the whole test page: one Node file that serves the page and the route, the field, and the browser script. Our vanilla JavaScript tutorial builds the proxy and a clickable list step by step and leaves keyboard navigation as a next step; this code adds it. If your app already serves its own pages, keep only the /api/address-suggest route. The server (Node 18 or later, no packages):

// server.mjs: Node 18+, no packages. Keeps the API key on the server.
import http from "node:http";
import { readFile } from "node:fs/promises";

const KEY = process.env.STHAN_API_KEY;
const FILES = { "/": "index.html", "/browser.js": "browser.js" };
const TYPES = { "/": "text/html", "/browser.js": "text/javascript" };

http.createServer(async (req, res) => {
  const url = new URL(req.url, "http://localhost");
  if (FILES[url.pathname]) {
    const file = await readFile(new URL(FILES[url.pathname], import.meta.url));
    res.writeHead(200, { "Content-Type": TYPES[url.pathname] }).end(file);
    return;
  }
  if (url.pathname !== "/api/address-suggest") {
    res.writeHead(404).end();
    return;
  }
  const q = (url.searchParams.get("q") || "").trim();
  if (q.length < 3 || q.length > 200) {
    res.writeHead(200, { "Content-Type": "application/json" }).end("[]");
    return;
  }
  let list = null;
  try {
    const upstream = await fetch(
      "https://api.sthan.io/AutoComplete/USA/Address/" + encodeURIComponent(q),
      { headers: { Authorization: "Bearer " + KEY } }
    );
    console.log("upstream call:", q.length, "chars, status", upstream.status);
    if (upstream.ok) {
      const body = await upstream.json();
      list = Array.isArray(body.Result) ? body.Result : [];
    }
  } catch (err) {
    console.log("upstream error:", err.message);
  }
  res.writeHead(list ? 200 : 502, { "Content-Type": "application/json" });
  res.end(JSON.stringify(list || []));
}).listen(3000);

The field, with a visible label and the combobox attributes screen readers use:

<!doctype html><html><body>
<label for="address">Street address</label>
<input id="address" autocomplete="off" role="combobox" aria-autocomplete="list" aria-expanded="false" aria-controls="suggestions">
<ul id="suggestions" role="listbox" aria-label="Address suggestions"></ul>
<script src="/browser.js"></script>
</body></html>

The browser script. It waits for a 300 millisecond pause, cancels a request when a newer keystroke or a choice comes after it, and supports Up, Down, Enter and Escape. We checked the keys and attributes in a script; we did not test it with a screen reader, so do that before you ship:

const input = document.getElementById("address");
const list = document.getElementById("suggestions");
let timer, controller, items = [], active = -1, latest = 0;

function cancelPending() {
  clearTimeout(timer);       // a lookup that has not started yet
  latest++;                  // any answer still on its way is now out of date
  if (controller) controller.abort();
}

input.addEventListener("input", () => {
  cancelPending();
  timer = setTimeout(async () => {
    const ticket = latest;
    controller = new AbortController();
    let next = [];
    try {
      const r = await fetch("/api/address-suggest?q=" + encodeURIComponent(input.value),
                            { signal: controller.signal });
      if (r.ok) next = await r.json();
    } catch (err) { /* aborted or network error: show no new suggestions */ }
    if (ticket !== latest) return; // a newer keystroke or a choice came after this request
    items = next;
    active = -1;
    render();
  }, 300); // wait for a 300 ms pause in typing
});

input.addEventListener("keydown", (e) => {
  if (e.key === "Escape") { // close, even while a lookup is still waiting or on its way
    cancelPending();
    items = [];
    active = -1;
    render();
    return;
  }
  if (items.length === 0) return; // no list open: arrow keys and Enter do nothing
  if (e.key === "ArrowDown") active = Math.min(active + 1, items.length - 1);
  else if (e.key === "ArrowUp") active = Math.max(active - 1, 0);
  else if (e.key === "Enter" && active >= 0) { e.preventDefault(); choose(items[active]); return; }
  else return;
  render();
});

function render() {
  list.innerHTML = "";
  items.forEach((text, i) => {
    const li = document.createElement("li");
    li.id = "suggestion-" + i;
    li.textContent = text;
    li.setAttribute("role", "option");
    li.setAttribute("aria-selected", i === active);
    li.addEventListener("mousedown", () => choose(text));
    list.appendChild(li);
  });
  input.setAttribute("aria-expanded", items.length > 0);
  if (active >= 0) input.setAttribute("aria-activedescendant", "suggestion-" + active);
  else input.removeAttribute("aria-activedescendant");
}

function choose(text) {
  cancelPending(); // so a late answer cannot reopen the list
  input.value = text;
  items = [];
  active = -1;
  render();
  // next: verify the chosen address once, on your server
}

On the server, only text of 3 to 200 characters reaches the API. The key comes from an environment variable, so it never reaches the browser. An open route like this can be called by anyone who finds it, so put it behind your own rate limit or session check before you ship.

What our test returned

On October 16, 2026 we ran the page against the live sthan.io API. A browser typed 1600 pennsylvania ave nw wa at 60 milliseconds per key, then pressed Down and Enter. The server logged one call to the API for all 27 characters, because no gap between keys reached 300 milliseconds. That is an artificial best case; a person who pauses while typing sends more requests. The list showed one suggestion:

["1600 Pennsylvania Ave NW, Washington, DC 20500-0005"]

After Enter, the field held 1600 Pennsylvania Ave NW, Washington, DC 20500-0005 and the list closed. A two-character input made no API call. The raw API response wraps the list in an envelope with a Result property, which is why the route returns body.Result; sthan.io's docs say their examples "show only the Result field contents for clarity."

Using React, Vue or Angular? The same flow is shown per framework in address autocomplete in React, Vue and Angular.

Where sthan.io fits. sthan.io's US Address Autocomplete returns complete US addresses as people type, with apartment and suite numbers where the address has them, and ZIP+4. The free tier is 100,000 requests a month with no credit card; paid plans start at $7 a month for 100,000. For the verify-once step, sthan.io's verification API returns a deliverability status and ZIP+4, with paid plans from $12 a month for 10,000. sthan.io is not CASS-certified.

Frequently Asked Questions

Yes. On October 16, 2026, sthan.io listed 100,000 US autocomplete requests a month free with no credit card, Google listed 10,000 free Autocomplete Requests a month, Geoapify 3,000 credits a day, and Mapbox Address Autofill 1,000 sessions a month. Radar's pricing page says it does not currently offer a free tier.
Without a session token, each Autocomplete (New) request is billed at $2.83 per 1,000 after 10,000 free a month. A session that ends in Place Details Essentials bills up to 12 autocomplete requests plus the Place Details call, and a session that ends in Address Validation makes the autocomplete requests free and bills the validation at the Enterprise SKU. Ending a session with Place Details Essentials (IDs Only) bills every autocomplete request as if you had no session.
It depends on how often you call. Smarty says that sending a query on every keystroke might use around ten lookups per address. In our test, keys typed 60 milliseconds apart with a 300 millisecond wait sent one request for 27 characters, but that typing never paused; a person who stops mid-address sends more.
Yes, once, on your server. People can edit the line after they pick it, for example to add an apartment number, so one verification call on submit returns a status for the final address. sthan.io's verification API returns a deliverability status and ZIP+4.
You can, but anyone can then read your API key in the page source. A small server route that adds the key keeps it private and lets you skip inputs shorter than three characters, the minimum sthan.io's docs give for best results.

Sources

All read October 16, 2026. Prices change; check the vendor page before you buy.

100,000 free autocomplete requests a month

No credit card. Complete US addresses with apartment and suite numbers and ZIP+4 as people type.

Marcus Chen
Written by Marcus Chen

Marcus Chen writes about address autocomplete and validation in JavaScript, Node.js, React, Vue and Next.js.

More from Marcus Chen