Ocultar datos personales

Publica el mensaje, no el número de teléfono

La gente pega su teléfono, su cuenta bancaria o el número de su tarjeta en un comentario, un anuncio o un chat de soporte sin pensarlo. ToxicFilter los encuentra, comprueba cada número por su dígito de control y, con redact activado, te devuelve el mismo texto con cada dato tapado: publicas lo que escribieron, no lo que debían haberse guardado.

Cómo funciona

  1. Se lee el texto tal como llega

    Teléfonos, correos y números se buscan en el texto original, nunca en una copia normalizada, así que cada hallazgo sabe exactamente dónde empieza y cuánto ocupa.

  2. Los números tienen que cuadrar

    Un IBAN tiene que pasar el módulo 97, una tarjeta el algoritmo de Luhn y empezar como las de un emisor real, y un DNI o NIE tiene que llevar su letra. Una referencia de pedido de dieciséis cifras no es una tarjeta y no se trata como tal.

  3. El texto vuelve tapado

    Con redact: true la respuesta trae redacted: tu texto con cada hallazgo sustituido por [redacted]. Los que se solapan se unen antes y se sustituyen de derecha a izquierda, para que no quede medio número a la vista.

  4. Tus reglas deciden el resto

    Por defecto los datos personales quedan en revisión y un número de tarjeta se rechaza. Una política puede mover esas líneas: una app de citas puede rechazar cualquier teléfono y un servicio de soporte quedarse solo con el texto tapado.

Míralo en acción

  1. 01 Un teléfono y un correo en un chat de soporte
  2. 02 Un correo escrito para colarse
  3. 03 Una cuenta bancaria en un anuncio
  4. 04 Un número de tarjeta en un comentario
  5. 05 Un número largo que no es una tarjeta

Un teléfono y un correo en un chat de soporte POST /v1/text with redact: true

Mi paquete no ha llegado. Llámame al +44 7700 900123 o escríbeme a ana.lopez@example.com, estoy en casa toda la semana.

review 8 ms
  • Contains an email address.
  • Contains what looks like a phone number.

Queda en revisión en vez de rechazarse, y el mensaje vuelve con los dos datos tapados. La queja por el paquete sigue ahí para quien la conteste.

La respuesta, resumida
{
  "decision": "review",
  "flagged": [
    "personal_data"
  ],
  "scores": {
    "personal_data": 0.6
  },
  "signals": [
    {
      "category": "personal_data",
      "score": 0.6,
      "reason": "Contains an email address.",
      "evidence": [
        "ana.lopez@example.com"
      ]
    },
    {
      "category": "personal_data",
      "score": 0.5,
      "reason": "Contains what looks like a phone number.",
      "evidence": [
        "447•••••••23"
      ]
    }
  ],
  "redacted": "Mi paquete no ha llegado. Llámame al [redacted] o escríbeme a [redacted], estoy en casa toda la semana.",
  "model": {
    "read": false
  },
  "took_ms": 8
}

Un correo escrito para colarse POST /v1/text with redact: true

Aquí no dejan poner correos, así que: ana.lopez (arroba) example (punto) com. Mándame ahí las fotos.

review 7 ms
  • Domain written with its dot spelled out or bracketed, which only makes sense to dodge a filter.
  • Contains an email address.
  • Email address written as "name at domain dot com" to get past a filter.

Se escribe con (arroba) y (punto) justo porque una dirección normal se elimina. Aun así se encuentra y se tapa, y el disfraz se señala aparte como evasión.

La respuesta, resumida
{
  "decision": "review",
  "flagged": [
    "evasion",
    "personal_data"
  ],
  "scores": {
    "evasion": 0.7,
    "personal_data": 0.6
  },
  "signals": [
    {
      "category": "evasion",
      "score": 0.65,
      "reason": "Domain written with its dot spelled out or bracketed, which only makes sense to dodge a filter.",
      "evidence": [
        "example (punto) com"
      ]
    },
    {
      "category": "personal_data",
      "score": 0.6,
      "reason": "Contains an email address.",
      "evidence": [
        "ana.lopez (arroba) example (punto) com"
      ]
    },
    {
      "category": "evasion",
      "score": 0.7,
      "reason": "Email address written as \"name at domain dot com\" to get past a filter.",
      "evidence": [
        "ana.lopez (arroba) example (punto) com"
      ]
    }
  ],
  "redacted": "Aquí no dejan poner correos, así que: [redacted]. Mándame ahí las fotos.",
  "model": {
    "read": false
  },
  "took_ms": 7
}

Una cuenta bancaria en un anuncio POST /v1/text with redact: true

Habitación en piso compartido, 450 al mes. Para reservarla, haz la transferencia de la fianza a ES91 2100 0418 4502 0005 1332.

review 7 ms
  • Contains 1 bank account number(s) (IBAN). Publishing one invites fraud against whoever owns it.

El IBAN pasa el módulo 97, así que es una cuenta y no una ristra de cifras. El anuncio queda en revisión y vuelve con la cuenta tapada.

La respuesta, resumida
{
  "decision": "review",
  "flagged": [
    "personal_data"
  ],
  "scores": {
    "personal_data": 0.9
  },
  "signals": [
    {
      "category": "personal_data",
      "score": 0.9,
      "reason": "Contains 1 bank account number(s) (IBAN). Publishing one invites fraud against whoever owns it.",
      "evidence": [
        "ES••••••••••••••••••1332"
      ]
    }
  ],
  "redacted": "Habitación en piso compartido, 450 al mes. Para reservarla, haz la transferencia de la fianza a [redacted].",
  "model": {
    "read": false
  },
  "took_ms": 7
}

Un número de tarjeta en un comentario POST /v1/text with redact: true

¿Alguien sabe por qué me rechazan esta tarjeta? 4111 1111 1111 1111, caduca en 09/28.

block 8 ms
  • Contains 1 payment card number(s). This one is not a guess: the digits check out.

Pasa Luhn y empieza como la tarjeta de un emisor real, así que no es una suposición, y por defecto es el único dato personal que se rechaza. La evidencia solo enseña las cuatro últimas cifras.

La respuesta, resumida
{
  "decision": "block",
  "flagged": [
    "personal_data"
  ],
  "scores": {
    "personal_data": 0.95
  },
  "signals": [
    {
      "category": "personal_data",
      "score": 0.95,
      "reason": "Contains 1 payment card number(s). This one is not a guess: the digits check out.",
      "evidence": [
        "••••••••••••1111"
      ]
    }
  ],
  "redacted": "¿Alguien sabe por qué me rechazan esta tarjeta? [redacted], caduca en 09/28.",
  "model": {
    "read": false
  },
  "took_ms": 8
}

Un número largo que no es una tarjeta POST /v1/text

Sigo esperando el pedido 4000 1234 5678 9011, que hice el lunes pasado. ¿Sabéis algo?

allow 7 ms

Dieciséis cifras que no pasan la comprobación, así que no se señala nada. Sin el dígito de control, esto saltaría en cada ticket de soporte y alguien lo desactivaría en una semana.

La respuesta, resumida
{
  "decision": "allow",
  "flagged": [],
  "signals": [],
  "model": {
    "read": false
  },
  "took_ms": 7
}

Míralo en acción

Un teléfono y un correo en un chat de soporte POST /v1/text with redact: true

Mi paquete no ha llegado. Llámame al +44 7700 900123 o escríbeme a ana.lopez@example.com, estoy en casa toda la semana.

review 8 ms
  • Contains an email address.
  • Contains what looks like a phone number.

Queda en revisión en vez de rechazarse, y el mensaje vuelve con los dos datos tapados. La queja por el paquete sigue ahí para quien la conteste.

La respuesta, resumida
{
  "decision": "review",
  "flagged": [
    "personal_data"
  ],
  "scores": {
    "personal_data": 0.6
  },
  "signals": [
    {
      "category": "personal_data",
      "score": 0.6,
      "reason": "Contains an email address.",
      "evidence": [
        "ana.lopez@example.com"
      ]
    },
    {
      "category": "personal_data",
      "score": 0.5,
      "reason": "Contains what looks like a phone number.",
      "evidence": [
        "447•••••••23"
      ]
    }
  ],
  "redacted": "Mi paquete no ha llegado. Llámame al [redacted] o escríbeme a [redacted], estoy en casa toda la semana.",
  "model": {
    "read": false
  },
  "took_ms": 8
}

Un correo escrito para colarse POST /v1/text with redact: true

Aquí no dejan poner correos, así que: ana.lopez (arroba) example (punto) com. Mándame ahí las fotos.

review 7 ms
  • Domain written with its dot spelled out or bracketed, which only makes sense to dodge a filter.
  • Contains an email address.
  • Email address written as "name at domain dot com" to get past a filter.

Se escribe con (arroba) y (punto) justo porque una dirección normal se elimina. Aun así se encuentra y se tapa, y el disfraz se señala aparte como evasión.

La respuesta, resumida
{
  "decision": "review",
  "flagged": [
    "evasion",
    "personal_data"
  ],
  "scores": {
    "evasion": 0.7,
    "personal_data": 0.6
  },
  "signals": [
    {
      "category": "evasion",
      "score": 0.65,
      "reason": "Domain written with its dot spelled out or bracketed, which only makes sense to dodge a filter.",
      "evidence": [
        "example (punto) com"
      ]
    },
    {
      "category": "personal_data",
      "score": 0.6,
      "reason": "Contains an email address.",
      "evidence": [
        "ana.lopez (arroba) example (punto) com"
      ]
    },
    {
      "category": "evasion",
      "score": 0.7,
      "reason": "Email address written as \"name at domain dot com\" to get past a filter.",
      "evidence": [
        "ana.lopez (arroba) example (punto) com"
      ]
    }
  ],
  "redacted": "Aquí no dejan poner correos, así que: [redacted]. Mándame ahí las fotos.",
  "model": {
    "read": false
  },
  "took_ms": 7
}

Una cuenta bancaria en un anuncio POST /v1/text with redact: true

Habitación en piso compartido, 450 al mes. Para reservarla, haz la transferencia de la fianza a ES91 2100 0418 4502 0005 1332.

review 7 ms
  • Contains 1 bank account number(s) (IBAN). Publishing one invites fraud against whoever owns it.

El IBAN pasa el módulo 97, así que es una cuenta y no una ristra de cifras. El anuncio queda en revisión y vuelve con la cuenta tapada.

La respuesta, resumida
{
  "decision": "review",
  "flagged": [
    "personal_data"
  ],
  "scores": {
    "personal_data": 0.9
  },
  "signals": [
    {
      "category": "personal_data",
      "score": 0.9,
      "reason": "Contains 1 bank account number(s) (IBAN). Publishing one invites fraud against whoever owns it.",
      "evidence": [
        "ES••••••••••••••••••1332"
      ]
    }
  ],
  "redacted": "Habitación en piso compartido, 450 al mes. Para reservarla, haz la transferencia de la fianza a [redacted].",
  "model": {
    "read": false
  },
  "took_ms": 7
}

Un número de tarjeta en un comentario POST /v1/text with redact: true

¿Alguien sabe por qué me rechazan esta tarjeta? 4111 1111 1111 1111, caduca en 09/28.

block 8 ms
  • Contains 1 payment card number(s). This one is not a guess: the digits check out.

Pasa Luhn y empieza como la tarjeta de un emisor real, así que no es una suposición, y por defecto es el único dato personal que se rechaza. La evidencia solo enseña las cuatro últimas cifras.

La respuesta, resumida
{
  "decision": "block",
  "flagged": [
    "personal_data"
  ],
  "scores": {
    "personal_data": 0.95
  },
  "signals": [
    {
      "category": "personal_data",
      "score": 0.95,
      "reason": "Contains 1 payment card number(s). This one is not a guess: the digits check out.",
      "evidence": [
        "••••••••••••1111"
      ]
    }
  ],
  "redacted": "¿Alguien sabe por qué me rechazan esta tarjeta? [redacted], caduca en 09/28.",
  "model": {
    "read": false
  },
  "took_ms": 8
}

Un número largo que no es una tarjeta POST /v1/text

Sigo esperando el pedido 4000 1234 5678 9011, que hice el lunes pasado. ¿Sabéis algo?

allow 7 ms

Dieciséis cifras que no pasan la comprobación, así que no se señala nada. Sin el dígito de control, esto saltaría en cada ticket de soporte y alguien lo desactivaría en una semana.

La respuesta, resumida
{
  "decision": "allow",
  "flagged": [],
  "signals": [],
  "model": {
    "read": false
  },
  "took_ms": 7
}

Los datos personales en el contenido de tus usuarios, explicados

Qué se encuentra, cómo se comprueba un número y qué hace el texto tapado.

Por qué tapar los datos personales en vez de rechazar el mensaje

Rechazar un comentario porque lleva un número de teléfono tira a la basura todo lo demás que escribió esa persona. En un marketplace o en un chat de soporte casi nunca compensa: el mensaje está bien, solo una parte no debería ser pública. Tapar esa parte conserva la conversación y quita el número, y el autor no tiene que volver a escribirlo todo.

Qué encuentra

Correos electrónicos, también en las formas que la gente usa porque sabe que una dirección normal se elimina: nombre (arroba) dominio (punto) com, (at) y (dot), [at] y [dot]. Teléfonos, como secuencias de al menos nueve cifras, con o sin separadores y prefijo internacional. Cuentas bancarias en formato IBAN, números de tarjeta, DNI y NIE, el NIR francés, el codice fiscale italiano, el BSN neerlandés, el NIF portugués y la Steuer-ID alemana, y matrículas españolas. Cada uno es una señal de personal_data con el motivo en una frase, y el correo disfrazado añade otra de evasion.

Cómo se comprueba un número antes de señalarlo

Un número largo no es un dato personal por sí mismo; la mayoría son referencias de pedido, códigos de envío o números de factura. Por eso todo lo que tiene dígito de control se verifica. Un IBAN se reordena, sus letras se pasan a números y el resto de dividir entre 97 tiene que ser uno. Una tarjeta tiene que pasar Luhn y empezar por un prefijo que use un emisor real, y así un teléfono con la longitud justa no se cuela una de cada diez veces. Un DNI o un NIE tiene que acabar en la letra que sale de su número módulo 23, y los demás números nacionales llevan su propio dígito o letra de control, que se comprueba igual. Una matrícula no tiene dígito de control, y por eso puntúa más bajo que el resto.

Qué devuelve redact

Con redact: true, la respuesta trae redacted: el texto que enviaste con cada hallazgo sustituido por [redacted]. Las posiciones salen de detectores que leen el texto original, así que el tapado cae sobre las palabras correctas. Los hallazgos que se solapan se unen antes de sustituir nada, porque un IBAN contiene una serie de cifras que el detector de teléfonos también ve, y tapar una y saltarse la otra dejaría media cuenta publicada. La sustitución va de derecha a izquierda, porque cada tapado cambia la longitud del texto. Las posiciones no tienen tope: un mensaje con cuarenta direcciones vuelve con cuarenta tapados.

Una evidencia que no repite el número

La señal enseña lo que se encontró, para que un moderador vea por qué se retuvo un mensaje. Los números de tarjeta aparecen solo con sus cuatro últimas cifras y los teléfonos sin la parte central, porque un detector que existe para avisar de un número que no debería ser público no puede ser el que lo copie en los logs y en las respuestas de la API.

Cómo se reparte el trabajo

Las comprobaciones instantáneas resuelven los casos claros en torno a un milisegundo, el modelo lee lo que depende del contexto, y tus reglas y tu equipo tienen la última palabra.

  • Comprobado, nunca adivinado

    Todo lo que lleva dígito de control se verifica antes de señalarlo: un IBAN por módulo 97, una tarjeta por Luhn y un prefijo de emisor real, un DNI o un NIE por su letra. Un número que no pasa la comprobación no se señala, así que las referencias de pedido y los códigos de envío quedan como están.

  • Tu política decide

    Un teléfono en un anuncio puede ser el del propio vendedor y estar bien ahí. El detector dice que está; tu política dice si se retiene, se rechaza o solo se tapa.

  • No se guarda nada

    El registro guarda el veredicto y un hash del contenido, nunca el contenido. Los números de tarjeta y de teléfono van tapados incluso en la evidencia de la respuesta, así que el detector no los copia a ningún sitio.

Preguntas frecuentes

¿Cómo quito teléfonos y correos de los comentarios de mis usuarios?

Envía el comentario a POST /v1/text con redact: true. La respuesta trae redacted, el mismo texto con cada teléfono y cada correo sustituidos por [redacted], junto a la decisión y las señales. Publicas redacted en lugar del original.

¿Detecta correos escritos como nombre (arroba) dominio (punto) com?

Sí. Las formas con (at), [at] y (dot), con arroba y punto, y nombre at gmail.com se leen como direcciones, se tapan como cualquier otra y se señalan además como evasión, porque escribirlas así es un intento de saltarse un filtro.

¿Cómo distingue un número de tarjeta de una referencia de pedido?

Por el dígito de control. Una tarjeta tiene que pasar el algoritmo de Luhn y empezar por un prefijo que use un emisor real; un IBAN tiene que pasar el módulo 97; un DNI o un NIE tiene que llevar la letra que le corresponde a su número. Un número que no lo cumple no se señala.

¿Los datos personales se bloquean o solo se marcan?

Con las líneas de serie, un teléfono, un correo, un IBAN, un DNI o una matrícula quedan en revisión, y un número de tarjeta se rechaza. Son líneas de tu política como cualquier otra: puedes rechazar con una puntuación más baja o no rechazar nunca y quedarte con el texto tapado.

¿ToxicFilter guarda los datos personales que encuentra?

El registro guarda el veredicto y un hash del contenido, nunca el contenido, y las señales guardadas no llevan evidencia. Los números de tarjeta y de teléfono aparecen tapados incluso en la evidencia de la respuesta, para que el detector no los copie a ningún sitio.

¿Puede encontrar direcciones de casa?

Las direcciones quedan en manos de tus reglas, a propósito. Teléfonos, cuentas, tarjetas y documentos tienen una estructura o un dígito de control que hace fiable la coincidencia, y eso es lo que deja tranquilos los mensajes normales. Si en tu web importan las direcciones, las listas de palabras de tu política pueden recoger los nombres de calle o los códigos postales que te interesen.

Sigue leyendo

Pruébalo con tu tráfico real

2.000 créditos al mes en el plan gratuito, sin tarjeta. Suficiente para pasarle una semana de tu propio contenido y ver qué opina de él.