{
  "slug": "ip-log-anonymizer",
  "name": "gizza-ai/ip-log-anonymizer",
  "version": "0.1.0",
  "title": "IP Log Anonymizer — Mask, Hash or Redact IPs for GDPR Logs",
  "description": "Anonymize IPv4 & IPv6 addresses in a log in your browser: GA/Matomo-style masking, salted SHA-256 pseudonyms, or fixed redaction. Ports & timestamps kept. Free, private.",
  "tags": [
    "ip anonymizer",
    "ip address masking",
    "gdpr log anonymizer",
    "anonymize ip",
    "ip log redaction",
    "mask ip address",
    "hash ip address",
    "log pseudonymization"
  ],
  "category": "network",
  "urls": {
    "page": "https://gizza.ai/tools/ip-log-anonymizer/",
    "markdown": "https://gizza.ai/tools/ip-log-anonymizer/index.md",
    "descriptor": "https://gizza.ai/tools/ip-log-anonymizer/tool.json",
    "deep_link_example": "https://gizza.ai/tools/ip-log-anonymizer/?text=203.0.113.45%20-%20-%20%5B10%2FJul%2F2026%3A13%3A55%3A36%20%2B0000%5D%20%22GET%20%2Findex.html%20HTTP%2F1.1%22%20200%202326%0A198.51.100.7%20-%20-%20%5B10%2FJul%2F2026%3A13%3A55%3A37%20%2B0000%5D%20%22POST%20%2Flogin%20HTTP%2F1.1%22%20401%2012&mode=mask&ipv4_octets=1&ipv6_groups=5&salt=e.g.%20a%20per-project%20random%20string&hash_length=12&replacement=%5BIP%5D&skip_private=true"
  },
  "cli": "gizza tool ip-log-anonymizer \"203.0.113.45 - - [10/Jul/2026:13:55:36 +0000] \"GET /index.html HTTP/1.1\" 200 2326\n198.51.100.7 - - [10/Jul/2026:13:55:37 +0000] \"POST /login HTTP/1.1\" 401 12\"",
  "tool": {
    "description": "Anonymize every IPv4 and IPv6 address inside a log or text for GDPR-compliant analytics, in place. Three modes: 'mask' zeros trailing octets/hextets like Google Analytics / Matomo (ipv4_octets default 1, ipv6_groups default 5 = keep the /48); 'hash' replaces each address with a short salted SHA-256 token (set `salt` to a secret; `hash_length` chars kept); 'redact' swaps a fixed `replacement` token. Set skip_private=true to leave internal 10.x/192.168.x/127.x/fc00::/fe80:: addresses untouched. Addresses are validated before replacement; ports, paths, and timestamps are preserved. Runs locally.",
    "parameters": {
      "additionalProperties": false,
      "properties": {
        "hash_length": {
          "default": 12,
          "description": "hash mode: how many hex characters of the SHA-256 digest to keep for each token (4-64; default 12). Longer = fewer collisions.",
          "maximum": 64,
          "minimum": 4,
          "type": "integer"
        },
        "ipv4_octets": {
          "default": 1,
          "description": "mask mode: how many trailing IPv4 octets to zero (1 = 203.0.113.45→203.0.113.0, the Google Analytics default; 2 matches Matomo's stricter default; 4 = 0.0.0.0). 0-4.",
          "maximum": 4,
          "minimum": 0,
          "type": "integer"
        },
        "ipv6_groups": {
          "default": 5,
          "description": "mask mode: how many trailing IPv6 16-bit hextets to zero (5 = zero the last 80 bits, keeping the /48 prefix — the common GA/Cloudflare default; 8 zeros the whole address). 0-8.",
          "maximum": 8,
          "minimum": 0,
          "type": "integer"
        },
        "mode": {
          "default": "mask",
          "description": "How to anonymize each address: 'mask' zeros the trailing octets/hextets (GA/Matomo-style truncation, keeps geolocation); 'hash' replaces it with a short salted SHA-256 token (stable pseudonym, not reversible); 'redact' swaps in a fixed placeholder token.",
          "enum": [
            "mask",
            "hash",
            "redact"
          ],
          "type": "string"
        },
        "replacement": {
          "default": "[IP]",
          "description": "redact mode: the placeholder token that replaces each address (e.g. '[IP]', '[REDACTED]', 'x.x.x.x').",
          "type": "string"
        },
        "salt": {
          "default": "",
          "description": "hash mode: a secret string mixed in before hashing. Strongly recommended — a per-project random salt makes the pseudonyms un-guessable; an empty salt still hashes but is vulnerable to reverse lookup.",
          "type": "string"
        },
        "skip_private": {
          "default": false,
          "description": "When true, private/loopback/link-local addresses (10.x, 192.168.x, 127.x, fc00::/7, fe80::/10, …) are left untouched — they are not personal data. Default false anonymizes every address.",
          "type": "boolean"
        },
        "text": {
          "description": "The log or text to anonymize. Every valid IPv4 and IPv6 address is replaced in place; all other characters (paths, ports, timestamps) are left untouched.",
          "type": "string"
        }
      },
      "required": [
        "text"
      ],
      "type": "object"
    }
  }
}