Easy IP checker widget

December 5, 2025

Tiny IP Checker Widget with Copy Button

This is a tiny, copy-paste IP checker widget you can drop onto almost any page. It shows the visitor’s public IP address and includes a one-click Copy button so they can quickly paste it into a ticket, chat, or email. It’s ideal for support pages, diagnostics, or simple “what’s my IP?” helpers without building a full app or dashboard.

The widget is designed to be small, readable, and easy to style. There’s no framework required, no build step, and no huge dependency tree. You just paste the HTML, CSS, and JavaScript block into your page and it does the rest.

What this widget does

When the page loads, the script asks a tiny external service what the visitor’s public IP address is. Once it gets a response, it displays the IP inside a compact card and enables the Copy button. If that first request fails, it falls back to a second endpoint and tries again before finally showing “Unavailable”.

The copy button uses the modern navigator.clipboard API when it’s available. On older browsers, it falls back to a simple textarea trick using document.execCommand('copy'). Either way, the visitor ends up with the IP address on their clipboard in a single click.

Copy-paste snippet (HTML, CSS & JavaScript)

You can paste this block into a page template, a help article, or a dedicated tools page. It renders a single card, fetches the IP, and wires up the Copy button for you.

<style>
  /* Tiny IP checker card */

  .vibe-ip-card {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 8px 10px;
    border: 1px solid #C4C6F5;
    background: #F9FAFF;
    font: 13px/1.4 system-ui, -apple-system, BlinkMacSystemFont,
          "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    border-radius: 10px;
  }

  .vibe-ip-label {
    font-weight: 600;
  }

  .vibe-ip-value {
    font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
                 "Liberation Mono", "Courier New", monospace;
    padding: 2px 6px;
    background: #F2F4FF;
    border-radius: 6px;
  }

  .vibe-ip-copy {
    appearance: none;
    border: 1px solid #A829A7;
    background: #A829A7;
    color: #fff;
    padding: 3px 8px;
    font-size: 12px;
    border-radius: 999px;
    cursor: pointer;
  }

  .vibe-ip-copy:hover {
    background: #8c1f8b;
  }

  .vibe-ip-copy[disabled] {
    opacity: 0.6;
    cursor: default;
  }
</style>

<div class="vibe-ip-card">
  <span class="vibe-ip-label">Your IP:</span>
  <span id="vibe-ip-value" class="vibe-ip-value">Checking…</span>
  <button id="vibe-ip-copy" class="vibe-ip-copy" type="button">Copy</button>
</div>

<script>
  // Vibe IP checker
  // Shows the visitor's public IP using a tiny external lookup.
  // Includes a copy button with fallback.

  (function () {
    var ipEl = document.getElementById('vibe-ip-value');
    var copyBtn = document.getElementById('vibe-ip-copy');
    if (!ipEl || !copyBtn) return;

    var state = { ip: '' };

    function setIP(text) {
      state.ip = text || '';
      ipEl.textContent = state.ip || 'Unavailable';
      copyBtn.disabled = !state.ip;
    }

    function fetchJson(url) {
      return fetch(url, {
        method: 'GET',
        cache: 'no-store',
        credentials: 'omit'
      }).then(function (r) {
        if (!r.ok) throw new Error('HTTP ' + r.status);
        return r.json();
      });
    }

    function loadIP() {
      // Primary: ipify (simple + widely used)
      fetchJson('https://api.ipify.org?format=json')
        .then(function (data) {
          if (data && data.ip) {
            setIP(data.ip);
            return;
          }
          throw new Error('No IP in response');
        })
        .catch(function () {
          // Fallback: try IPv6-capable endpoint
          fetchJson('https://api64.ipify.org?format=json')
            .then(function (data) {
              setIP(data && data.ip ? data.ip : '');
            })
            .catch(function () {
              setIP('');
            });
        });
    }

    function showCopyStatus(ok) {
      var original = copyBtn.textContent;
      copyBtn.textContent = ok ? 'Copied!' : 'Copy failed';
      setTimeout(function () {
        copyBtn.textContent = original;
      }, 1200);
    }

    copyBtn.addEventListener('click', function () {
      if (!state.ip) return;

      if (navigator.clipboard && navigator.clipboard.writeText) {
        navigator.clipboard.writeText(state.ip)
          .then(function () { showCopyStatus(true); })
          .catch(function () { showCopyStatus(false); });
        return;
      }

      // Old-school fallback
      var temp = document.createElement('textarea');
      temp.value = state.ip;
      temp.style.position = 'fixed';
      temp.style.left = '-9999px';
      document.body.appendChild(temp);
      temp.focus();
      temp.select();

      try {
        var ok = document.execCommand('copy');
        showCopyStatus(ok);
      } catch (e) {
        showCopyStatus(false);
      }

      document.body.removeChild(temp);
    });

    copyBtn.disabled = true;
    loadIP();
  })();
</script>

How to add it to your site

  1. Copy the entire block above, including the <style>, HTML, and <script> tags.
  2. Paste it into the page or template where you want the IP checker to appear.
  3. Save and reload the page in a browser.
  4. After a moment, the “Checking…” label should turn into your public IP and the Copy button should become active.

If you use a shared layout or theme file, you can paste the widget there so it appears on multiple pages. For example, you might have a dedicated “Tools” page where this card lives next to other small utilities.

Styling and customization

Colors & typography

The card is intentionally neutral so it drops into most designs. You can change the border color, background, or fonts in the .vibe-ip-card rules to better match your brand. The IP itself is rendered in a monospace font, which makes it easier to read and compare.

Copy button behavior

The widget disables the Copy button until an IP value is loaded. Once the IP is ready, the button becomes clickable and gives a quick “Copied!” or “Copy failed” status message. This keeps the interaction clear and avoids confusing clicks while the lookup is still in progress.

Notes

This widget shows the user’s public-facing IP (the one the internet sees), not necessarily their internal LAN IP. If they’re on a VPN, corporate network, or mobile carrier NAT, the result will reflect that outer connection point rather than the device’s local address.

If you ever want a zero-third-party version, you can build the same display with a tiny PHP endpoint that returns $_SERVER['REMOTE_ADDR'] and fetch it from this widget. But for a quick drop-in “what’s my IP?” tool, this version stays small, simple, and easy to integrate.

Comments (0)

No comments yet — be the first.

← Back to all scripts