Détecter le contenu dupliqué avec des shingles
Ce détecteur de contenu dupliqué compare deux textes à l’aide de suites de mots consécutifs et fournit un pourcentage de similarité clair.
Lancer gratuitement
Il normalise la casse et la ponctuation, crée un ensemble de segments pour chaque texte, puis mesure leur recoupement avec l’indice de Jaccard. Vous choisissez la taille des shingles et le pourcentage déclenchant le signalement. Le résultat est déterministe, vérifiable et utile pour contrôler des pages de destination, des fiches produit, des articles syndiqués et d’autres contenus avant leur publication.
Ce que révèle la similarité par shingles
Un shingle est une courte suite de mots consécutifs. Avec une taille de trois, une phrase produit des groupes couvrant les mots 1 à 3, 2 à 4, puis ainsi de suite. L’outil constitue ces ensembles pour les deux textes, compte les segments communs et divise ce nombre par le total des segments uniques présents dans l’un ou l’autre ensemble. Ce calcul de Jaccard donne le pourcentage de similarité. Il valorise les passages concordants tout en ignorant les différences de casse et de ponctuation qui ne modifient pas les mots. Il est donc plus instructif qu’un simple comptage de termes isolés : un vocabulaire courant ne crée pas de correspondance si les mots ne se suivent pas dans le même ordre local. Le score prouve un recoupement textuel, mais ne prédit aucune sanction d’un moteur de recherche. Une valeur élevée indique que les versions réutilisent de nombreuses formulations et méritent une relecture éditoriale. Une valeur faible indique une rédaction exacte différente, sans garantir qu’un texte soit original, juste, utile ou publiable.
Choisir la taille et le seuil
La taille par défaut est de trois mots, ce qui constitue un bon point de départ pour des contenus web ordinaires. Les petits shingles sont plus sensibles : ils repèrent de courts fragments communs, mais peuvent aussi compter des expressions banales présentes naturellement sur des pages sans rapport. Les grands shingles exigent de longues suites identiques ; ils limitent les coïncidences fortuites, mais peuvent manquer des passages légèrement reformulés. Choisissez la taille avant d’interpréter le pourcentage, car des scores obtenus avec des tailles différentes ne sont pas directement comparables. Le seuil de duplication commande uniquement le signalement renvoyé et ne change pas le calcul. Un seuil de 70 signale tout score supérieur ou égal à 70 pour cent. Calibrez cette valeur à partir d’exemples de votre propre fonds documentaire au lieu d’en faire une règle SEO universelle. Conservez les mêmes réglages pour un lot. Chaque texte doit comporter au moins autant de mots normalisés que la taille choisie ; sinon, la requête échoue afin d’éviter un pourcentage artificiel ou trompeur.
Transformer le résultat en décision éditoriale
Utilisez le score comme indicateur de tri dans votre processus de relecture. Commencez par comparer des pages visant des requêtes proches, des modèles alimentés par le même catalogue ou un brouillon avec les sources remises à la rédaction. Lorsqu’une paire est signalée, examinez les deux documents et cherchez la cause des shingles communs. La navigation, les mentions légales, les caractéristiques techniques et les appels à l’action standard peuvent légitimement se répéter. Des introductions, explications, avantages et conclusions concordants justifient davantage une réécriture. Préservez les faits qui doivent rester exacts, mais réorganisez et reformulez le contenu afin que chaque page réponde à une intention propre. Notez la taille et le seuil avec le résultat si vous avez besoin d’une piste d’audit reproductible. L’outil traite exactement deux textes par requête ; il n’explore pas les URL, ne recherche pas le web, n’identifie pas l’auteur initial et ne décide pas du classement. Pour auditer un site, sélectionnez d’abord des paires pertinentes, gardez des réglages constants et soumettez les scores élevés à une appréciation humaine plutôt que de supprimer ou rediriger automatiquement.
Cas d’usage
Relire des pages de destination proches
Comparez des pages visant des mots-clés voisins et trouvez les passages qui les rendent inutilement répétitives.
Contrôler les textes des fournisseurs
Mesurez dans quelle proportion une fiche produit révisée reprend encore le texte source du fabricant.
Trier les propositions éditoriales
Comparez un nouveau brouillon à un article existant et confiez les paires très proches à la rédaction.
Questions fréquentes
Comment le pourcentage de similarité est-il calculé ?
L’outil applique l’indice de Jaccard aux shingles uniques : les segments communs sont divisés par tous les segments uniques des deux textes, puis multipliés par 100.
Que se passe-t-il si un texte est plus court que la taille choisie ?
La requête renvoie une erreur de saisie en indiquant le texte trop court. Chacun doit contenir assez de mots pour former au moins un shingle.
Un signalement implique-t-il une sanction du moteur de recherche ?
Non. Il indique un recoupement de formulations au seuil choisi, sans prédire l’indexation, la canonisation, le classement ni une action du moteur.
La ponctuation ou la casse modifient-elles le score ?
Non. Unicode, la casse et la ponctuation sont normalisés avant la création des shingles. L’identité et l’ordre des mots restent déterminants.
Quel est le prix d’une requête API ?
Chaque requête API coûte $0.002. Vous pouvez aussi lancer gratuitement cette même vérification déterministe dans votre navigateur.
Pour les développeurs — accès API
Tout sur cette page est disponible par programmation. Cette section s'adresse aux équipes qui veulent l'intégrer à leurs systèmes ; les autres peuvent simplement utiliser l'outil ci-dessus.
Endpoint
Authentification par jeton Bearer : un seul POST met la tâche en file d’attente, et le résultat vous parvient par webhook ou lien signé.
Appeler depuis votre stack
curl -X POST https://api.kit.forhosting.com/seo/duplicate-content-check \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"text_a":"Search engines value useful original pages that answer a reader'\''s question clearly and completely.","text_b":"Search engines value useful original pages that answer a reader'\''s question clearly and completely."}'const res = await fetch("https://api.kit.forhosting.com/seo/duplicate-content-check", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"text_a": "Search engines value useful original pages that answer a reader's question clearly and completely.",
"text_b": "Search engines value useful original pages that answer a reader's question clearly and completely."
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/seo/duplicate-content-check",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"text_a": "Search engines value useful original pages that answer a reader's question clearly and completely.",
"text_b": "Search engines value useful original pages that answer a reader's question clearly and completely."
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/seo/duplicate-content-check", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"text_a":"Search engines value useful original pages that answer a reader\'s question clearly and completely.","text_b":"Search engines value useful original pages that answer a reader\'s question clearly and completely."}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"text_a":"Search engines value useful original pages that answer a reader's question clearly and completely.","text_b":"Search engines value useful original pages that answer a reader's question clearly and completely."}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/seo/duplicate-content-check", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Exemple de requête
{
"text_a": "Search engines value useful original pages that answer a reader's question clearly and completely.",
"text_b": "Search engines value useful original pages that answer a reader's question clearly and completely."
}Exemple de réponse
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "seo.duplicate_content_check",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}L’API est asynchrone : chaque appel renvoie un task_id immédiatement, puis vous interrogez l’état à raison d’une requête par seconde.
Tarifs
Le prix est publié, sans tokens ni crédits. Une tâche qui échoue n’est pas facturée.
Erreurs
| HTTP | Code | Signification |
|---|---|---|
401 | unauthorized | Clé API absente ou invalide : vérifiez l’en-tête Authorization. |
402 | insufficient_balance | Solde insuffisant : rechargez votre compte pour lancer cette tâche. |
404 | unknown_type | Type de tâche inconnu : vérifiez le champ type de votre requête. |
429 | rate_limited | Trop de requêtes : ralentissez la cadence, puis réessayez. |