Offline HTML tool to quickly generate addr:* tags for OSM mappers

What it does:

This is a lightweight offline tool I built to help manually add addresses in OpenStreetMap. You just fill in the base info, and it generates and copies incrementing addr:* tags for pasting into iD Editor.

  • Why it’s helpful:

It doesn’t require any installs, runs in your browser, and works offline. No importing, no data scraping—just a helper to speed up tagging during manual mapping. Real simple to make and run.

Code

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Offline Address Tagger</title>
  <style>
    body { font-family: Arial; padding: 20px; }
    input { margin: 5px; width: 200px; }
    button { margin: 5px; padding: 5px 10px; }
    #output { margin-top: 15px; white-space: pre; background: #f8f8f8; border: 1px solid #ccc; padding: 10px; width: 300px; }
  </style>
</head>
<body>
  <h2>Offline Address Tagger</h2>
  <label>Starting Number: <input id="start" type="number" value="100" /></label><br>
  <label>Increment: <input id="inc" type="number" value="2" /></label><br>
  <label>Street: <input id="street" type="text" /></label><br>
  <label>City: <input id="city" type="text" /></label><br>
  <label>State: <input id="state" type="text" /></label><br>
  <label>ZIP: <input id="zip" type="text" /></label><br>
  <label>County: <input id="county" type="text" /></label><br>
  <button onclick="start()">Start</button>
  <button onclick="next()">Next</button>
  <button onclick="copyOutput()">Copy</button>
  <span id="copyStatus" style="margin-left:10px; color:green;"></span>

  <div id="output">Output will appear here</div>

  <script>
    let current = 0;
    let increment = 1;
    let info = {};

    function start() {
      current = parseInt(document.getElementById('start').value, 10);
      increment = parseInt(document.getElementById('inc').value, 10);
      info = {
        street: document.getElementById('street').value,
        city: document.getElementById('city').value,
        state: document.getElementById('state').value,
        zip: document.getElementById('zip').value,
        county: document.getElementById('county').value,
      };
      generateOutput();
    }

    function next() {
      current += increment;
      generateOutput();
    }

    function generateOutput() {
      const out = `
addr:housenumber=${current}
addr:street=${info.street}
addr:city=${info.city}
addr:state=${info.state}
addr:postcode=${info.zip}
addr:county=${info.county}
addr:country=US
      `.trim();
      document.getElementById('output').innerText = out;
    }

    function copyOutput() {
      const text = document.getElementById('output').innerText;
      navigator.clipboard.writeText(text).then(() => {
        const status = document.getElementById('copyStatus');
        status.textContent = 'Copied!';
        setTimeout(() => { status.textContent = ''; }, 1500);
      }).catch(err => {
        console.error('Copy failed:', err);
      });
    }
  </script>
</body>
</html>

Save it as an html file and execute.

1 Like

Mobile-Friendly Version (Tested and working on iOS)

For those who use Go Map!! or edit OSM from their phone/tablet, here’s a touch-optimized version of the Offline Address Tagger.

  • No pop-ups
  • Large buttons for thumbs
  • Works great on mobile browsers like Safari or Chrome
  • Tested successfully on iOS
  • Just copy the output and paste into your tagging field in Go Map!!
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Offline Address Tagger (Mobile Friendly)</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    body { font-family: Arial, sans-serif; padding: 20px; font-size: 18px; }
    label, input { display: block; margin: 10px 0; width: 100%; max-width: 400px; }
    input { padding: 10px; font-size: 16px; }
    button { padding: 12px 20px; font-size: 16px; margin: 10px 5px 0 0; }
    #output { margin-top: 20px; white-space: pre-wrap; background: #f8f8f8; border: 1px solid #ccc; padding: 15px; max-width: 400px; }
    #copyStatus { margin-left: 10px; color: green; font-size: 16px; }
  </style>
</head>
<body>
  <h2>Offline Address Tagger</h2>
  <label>Starting Number: <input id="start" type="number" value="100" /></label>
  <label>Increment: <input id="inc" type="number" value="2" /></label>
  <label>Street: <input id="street" type="text" /></label>
  <label>City: <input id="city" type="text" /></label>
  <label>State: <input id="state" type="text" /></label>
  <label>ZIP: <input id="zip" type="text" /></label>
  <label>County: <input id="county" type="text" /></label>

  <button onclick="start()">Start</button>
  <button onclick="next()">Next</button>
  <button onclick="copyOutput()">Copy</button>
  <span id="copyStatus"></span>

  <div id="output">Output will appear here</div>

  <script>
    let current = 0;
    let increment = 1;
    let info = {};

    function start() {
      current = parseInt(document.getElementById('start').value, 10);
      increment = parseInt(document.getElementById('inc').value, 10);
      info = {
        street: document.getElementById('street').value,
        city: document.getElementById('city').value,
        state: document.getElementById('state').value,
        zip: document.getElementById('zip').value,
        county: document.getElementById('county').value,
      };
      generateOutput();
    }

    function next() {
      current += increment;
      generateOutput();
    }

    function generateOutput() {
      const out = `
addr:housenumber=${current}
addr:street=${info.street}
addr:city=${info.city}
addr:state=${info.state}
addr:postcode=${info.zip}
addr:county=${info.county}
addr:country=US
      `.trim();
      document.getElementById('output').innerText = out;
    }

    function copyOutput() {
      const text = document.getElementById('output').innerText;
      navigator.clipboard.writeText(text).then(() => {
        const status = document.getElementById('copyStatus');
        status.textContent = 'Copied!';
        setTimeout(() => { status.textContent = ''; }, 1500);
      }).catch(err => {
        console.error('Copy failed:', err);
      });
    }
  </script>
</body>
</html>
1 Like

I decided to host these two tools on my github to make it more accessible to all contributors.

I have the cpu version on my github here:

https://chmod-x0.github.io/OSM-Address-Tagger/

And this one for mobile use (Tested and working on iOS):

https://chmod-x0.github.io/OSM-Address-Tagger-Mobile/

1 Like

Very cute and useful!

I had another idea to make a single use website to split up US/Canada-ish addresses into their OSM fields so they are a bit more copy/pasteable. I mostly use it to tear apart text found on websites for POIs I am adding.

Little utilities like this can really help!

1 Like

I’m glad you appreciate it!

It’s definitely helped my workflow, that’s for sure. I know a lot of people like JOSM for automation but it’s too complicated for me, so this tool hits all the sweet spots for my use case.

1 Like

Probably would have been better if you just provided the static GitHub pages link to begin with. Nobody is going to download the html manually.

Also consider spending a little time learning responsive design. There’s absolutely no reason to have two different websites.

Here’s a good resource:

Also, adding dark mode is as simple as adding <meta name="color-scheme" content="light dark"> into the header.

1 Like

Thank you for the feedback.