Inteligência artificial, sem ruído.
Tutoriais11 min

Marca d’água em texto: como detectar quem copiou seus artigos com Python

Anthropic, Google e OpenAI já marcam bilhões de palavras por dia. Veja como aplicar marca d'água invisível em seus textos com Python — e o que sobrevive à cópia.

Marca d’água em texto: como detectar quem copiou seus artigos com Python

Por que isso importa agora

Em 2 de agosto de 2026, a Anthropic começou a aplicar marca d’água em todo texto gerado pelo Claude. Desde 2024, o Gemini (Google) usa o SynthID-Text, método publicado na Nature e posteriormente aberto ao público. A OpenAI construiu algo semelhante. A China exige rótulos embutidos em conteúdo gerado por IA desde setembro de 2025, e quase 190 organizações já assinaram o código de transparência da União Europeia.

O resultado: bilhões de palavras geradas todos os dias carregam uma marca invisível — não um metadado que some no “copiar e colar”, mas um sinal embutido nas próprias palavras. Se as big techs fazem isso, por que você não poderia? A resposta curta: você pode, e este guia mostra exatamente como, usando apenas Python e a biblioteca padrão.

A intuição de que “texto é só caractere” está errada. Há um século, cartógrafos, editores de dicionários e uma empresa de letras de música já descobriram isso — muito antes dos modelos de linguagem existirem.

O que você ganha (e o que não ganha)

Proteção contra cópia literal: detecta scraping e republicação de conteúdo word-for-word.
Identificação de vazamentos: cada cópia pode carregar um ID único de 32 bits (4 bilhões de destinatários possíveis).
Zero dependências: a técnica de caracteres invisíveis e a de escolha de palavras rodam só com a biblioteca padrão do Python.
Evidência estatística: um detector calcula um p-valor — não é um palpite.
Camadas independentes: você pode combinar técnicas que não interferem entre si.

⚠️ Não sobrevive à reescrita: paráfrase (humana ou por LLM) destrói a maioria das marcas.
⚠️ Não prova propriedade: a Genius pegou o Google com marca d’água e ainda assim perdeu a ação judicial.
⚠️ Custa qualidade: forçar escolhas de palavras piora a fluência do texto.
⚠️ Não é bala de prata: para reivindicação legal de autoria, nenhuma dessas técnicas basta.

A intuição da “moeda”: por que 30 acertos seguidos viram evidência

Imagine que, ao escrever, você faz repetidamente uma ação binária escondida: insere um de dois caracteres invisíveis, escolhe entre dois sinônimos ou seleciona entre duas palavras seguintes igualmente plausíveis. Um único acerto não prova nada — há 50% de chance de acontecer por acaso. Mas se 30 escolhas seguidas batem com a chave, a chance de isso ser aleatório é de aproximadamente 1 em 1 bilhão.

Essa probabilidade é o que dá força estatística à marca d’água — expressa formalmente como um p-valor. As três famílias de técnicas diferem apenas no que a “moeda” representa:

FamíliaA moedaOnde vive
Caracteres invisíveisum caractere de largura zero — presente ou ausenteentre as letras
Escolhas de palavras com chave“grande” vs. “amplo”; apóstrofo reto vs. curvonas palavras
Amostragem viciadaqual token o modelo emite a seguirdentro do gerador
As três famílias de marca d’água de texto e onde cada sinal se esconde.

Um século de marca d’água antes dos LLMs

A técnica é mais antiga do que parece. Cartógrafos inseriam ruas-armadilha (“trap streets”): em 1925, a General Drafting Company criou a cidade fictícia de Agloe, em Nova York — anos depois, uma loja abriu no cruzamento e adotou o nome. Enciclopédias plantavam entradas falsas (os “mountweazels”), como a fotógrafa fictícia Lillian Virginia Mountweazel e a palavra esquivalience no New Oxford American Dictionary.

As armadilhas-canário vão além: cada destinatário recebe uma versão ligeiramente diferente. Elon Musk afirmou que a Tesla usou isso em 2008, variando entre um ou dois espaços entre frases para formar uma assinatura binária única. E o caso mais famoso: a Genius alternou apóstrofos retos e curvos em código Morse para escrever REDHANDED em 301 músicas — e a marca apareceu em 116 resultados do Google. A empresa processou por US$ 50 milhões e perdeu em 2020, não porque a marca falhou, mas porque não era dona das letras (apenas as licenciava).

Técnica 1 — caracteres invisíveis

O Unicode inclui caracteres que ocupam zero espaço visível, como o espaço de largura zero (U+200B) e o não-joiner de largura zero (U+200C). Atribua um a “0” e outro a “1” e você tem um canal binário escondido dentro de texto aparentemente normal.

import re
ZERO, ONE = "\u200b", "\u200c"   # espaço de largura zero, não-joiner
ID_BITS, CRC_BITS = 32, 8
PAYLOAD_BITS = ID_BITS + CRC_BITS
SENTENCE_END = re.compile(r"(?<=[.!?])(?=\s)")

def embed(text, owner_id):
    bits = f"{owner_id:0{ID_BITS}b}{crc8(owner_id):0{CRC_BITS}b}"
    mark = "".join(ONE if b == "1" else ZERO for b in bits)
    marked = SENTENCE_END.sub(mark, text)
    return marked if mark in marked else text + mark

def strip(text):
    return text.replace(ZERO, "").replace(ONE, "")

Três escolhas fazem o trabalho pesado: um CRC de 8 bits evita falsos positivos (chance de 1 em 256 de um payload aleatório passar, e zero IDs falsos em 1.700 tentativas nos experimentos); o payload repetido após cada frase permite que até um parágrafo copiado contenha a marca completa; e o decodificador de janela deslizante testa cada janela de 40 bits possível, retornando o ID válido que aparece com mais frequência.

O que sobrevive: 150/150 cópias recuperadas em todos os canais mecânicos testados — converter UTF-8/UTF-16, ida e volta por JSON/HTML, Markdown, .docx, normalização NFKC, até copiar só os 50% centrais do parágrafo. O que mata: sanitização explícita (0/150) e limpeza por LLM (apenas 8%, pois modelos regeneram texto em vez de editar o fluxo de caracteres). A regra é simples: sobrevive ao transporte, não à reescrita.

Técnica 2 — escolhas de palavras com chave

Em vez de esconder entre caracteres, a segunda técnica esconde dentro da redação: pares como “grande/amplo”, “iniciar/começar”, “problema/questão”. Uma chave secreta decide qual membro do par usar em cada ocorrência, via HMAC sobre o contexto à esquerda:

import hmac, hashlib, math

def keyed_bit(key, context, pair):
    message = f"{context}|{pair[0]}".encode("utf-8")
    return hmac.new(key, message, hashlib.sha256).digest()[0] & 1

def detect(text, key):
    slots = scan(text, key)
    n = len(slots)
    hits = sum(s["on_key"] for s in slots)
    z = (hits - n/2) / math.sqrt(n/4) if n else 0.0
    p = 0.5 * math.erfc(z / math.sqrt(2)) if n else 1.0
    return {"slots": n, "hits": hits, "z": z, "p_value": p}

A grande vantagem: não há nada para remover. Sanitizadores, normalização Unicode, scrapers e conversões de arquivo não apagam a marca. Para destruí-la, é preciso reescrever as próprias palavras. O custo aparece na qualidade — nos testes, 100% dos parágrafos marcados ficaram menos fluentes e cerca de 1 em 6 ganhou um erro gramatical (“consertou uma problema“, “aqueceu e preço meu teto”).

O resultado prático: a marca de escolha de palavras funciona em comprimento de documento, não de tuíte. A detecção salta de 73,3% (parágrafo de ~215 palavras) para 100% (artigo de ~1.075 palavras).

Técnica 3 — marcar o significado

As duas primeiras técnicas falham sob paráfrase pela mesma razão: a marca vive na redação. E se ela vivesse no significado? É a ideia do PostMark (EMNLP 2024): mantenha uma lista secreta de palavras incomuns, use um modelo de embeddings (como bge-m3) para encontrar as mais relacionadas ao documento e peça a um LLM para tecê-las naturalmente no texto.

Se o significado permanece parecido, as mesmas palavras raras continuam relevantes — e um reescritor tende a mantê-las, porque agora elas carregam conteúdo real. Nos testes com k=12 palavras plantadas, a detecção após paráfrase subiu de 9,3% para 36,7% — a melhor taxa entre todas as famílias, mas ainda longe de confiável para reivindicação legal. A contrapartida é o aumento de 15,8% no comprimento do texto e a queda na naturalidade.

Técnica 4 — amostragem viciada (na geração)

Ao contrário das anteriores, esta precisa acontecer enquanto o modelo gera cada token. Um modelo de linguagem escolhe repetidamente o próximo token de uma distribuição de probabilidades — cada escolha é uma “moeda”, e uma página contém milhares delas. A marca d’água vicia essas escolhas aleatórias de um jeito que só o detector reconhece.

Há duas abordagens principais: a green-list (Kirchenbauer et al., 2023), que divide o vocabulário em lista verde/vermelha e dá um pequeno impulso aos tokens verdes; e o SynthID-Text (DeepMind, Nature 2024), que usa “tournament sampling” com um modo não-distorcionário que preserva a distribuição original dos tokens.

Tokens vistosKirchenbauer (aberto)SynthID-Text (aberto)
5028,3%60,0%
10053,3%86,7%
20078,3%96,7%
40095,0%100,0%
Taxa de detecção em texto aberto/criativo, por número de tokens vistos (calibrado a 1% de falso positivo).

O achado mais importante não foi qual marca venceu, mas quanta liberdade o modelo tinha. Em texto criativo, o SynthID detectou 100% dos textos a 400 tokens. Em texto factual (“liste os oito planetas em ordem”), ambos despencam — se o modelo não pode favorecer um token sem errar a resposta, não há moeda para viciar. É a maior limitação da marca d’água generativa: ela é naturalmente fraca em texto curto, factual, repetitivo, código e saídas altamente restritas. E a paráfrase remove a maior parte do sinal (SynthID caiu de 100% para 11,7%).

Qual marca para qual ameaça

Sua ameaçaUsePor quê
Scrapers republicando na íntegraCaracteres de largura zero100% por HTML/JSON/Markdown/docx; decodifica de meio parágrafo
Descobrir quem vazou um documentoLargura zero, ID único por cópia32 bits = 4 bilhões de destinatários; CRC evita acusação falsa
Republicação com edições levesEscolha de palavras com chaveNada a remover; sobrevive a 30% de frases apagadas (53%)
Texto passado por um LLMMarca semântica, taxa alta36,7% após paráfrase em k=12 — a melhor disponível, não uma garantia
Provar que uma informação específica é suaArmadilha-canárioGrátis, sem código; sobrevive se o detalhe for estrutural
Marcar texto que seu próprio LLM geraSynthID ou KirchenbauerIntegrado ao transformers; exige controle no tempo de geração
Provar propriedade em juízoNenhuma das anterioresÉ problema jurídico, não técnico. Pergunte à Genius.
Regra de decisão: cada taxa vem dos experimentos do artigo original, não dos papers de origem.

Quatro regras práticas

  • Marque em comprimento de artigo, não de parágrafo. Mais texto é a robustez mais barata que você pode comprar.
  • Combine marcas independentes. Caracteres invisíveis e escolha de palavras não interferem entre si; um sanitizador que remove uma deixa a outra intacta.
  • Calibre em texto não marcado primeiro. Defina limiares usando texto humano que você nunca marcou — essa checagem expôs um detector que parecia confiável.
  • Guarde a chave ao publicar. Registre a chave, o ID ou a lista de palavras. Se você não consegue reproduzir a detecção, não tem uma marca d’água de verdade.

Troubleshooting: erros comuns e como resolver

“O detector marca texto limpo como positivo.” → Você não está calibrando em texto não marcado. Rode o detector sobre 50-100 passagens humanas antes de definir o limiar de z ≥ 2,45.

“A marca some ao colar no Word/Google Docs.” → Caracteres de largura zero sobrevivem a .docx, HTML e JSON, mas um sanitizador explícito os remove. Para resistir, combine com a técnica de escolha de palavras (nada a remover).

“A marca sumiu depois que reescreveram meu texto.” → Esperado. Nenhuma marca de redação sobrevive à paráfrase. Para texto que será reescrito, use a marca semântica (k=12) — e ainda assim aceite que é ~1/3 de detecção, não 100%.

“Detecção baixa em parágrafos curtos.” → Um parágrafo de ~215 palavras tem só ~13 “slots” utilizáveis — moedas demais para dar evidência estatística. Marque em artigo, não em tuíte.

“O Python não remove o U+200B com \\s.” → Correto: \\s não captura o espaço de largura zero, pois é caractere de formato Unicode, não espaço normal. Use .replace("\u200b", "") explicitamente.

Perguntas frequentes

Preciso de GPU para usar essas técnicas? As técnicas 1 e 2 rodam só com a biblioteca padrão do Python, em qualquer máquina. As técnicas 3 e 4 exigem um modelo (embeddings ou LLM), que pode rodar localmente ou via API.

Marca d’água prova que sou o autor? Não. Ela prova que sua versão do texto foi copiada. Provar propriedade é uma questão jurídica separada — o caso Genius vs. Google é o exemplo canônico.

Posso combinar técnicas? Sim, e é recomendado. Caracteres invisíveis + escolha de palavras são independentes e não interferem entre si.

Isso funciona em português? A técnica de caracteres invisíveis é agnóstica a idioma. A de escolha de palavras exige uma tabela de sinônimos auditada no idioma de destino. A semântica usa embeddings multilíngues (como bge-m3).

Onde encontro o código completo? O autor publicou o toolkit text-watermarking-toolkit no GitHub, com corpus, calibração e scripts reproduzíveis — tudo testado em Gemma-2-9b-it e Qwen2.5-7B-Instruct.



Descubra mais sobre noticiAI

Assine para receber nossas notícias mais recentes por e-mail.

R
Sobre o autorRedação Noticiai

Equipe editorial dedicada a explicar inteligência artificial com clareza, independência e contexto.