Vous avez un tableur de clients ou de fournisseurs français avec leur SIREN, et vous voulez savoir lesquels sont valides, lesquels sont actifs, lesquels ont cessé. Les vérifier un par un dans un navigateur prend un après-midi. Ce tutoriel donne un court script Python qui le fait pour vous, avec l’API de recherche gratuite de l’État, en respectant sa limite de débit. Nous l’avons lancé sur de vrais numéros le 10 octobre 2026 ; le résultat ci-dessous est celui qu’il a renvoyé.
Les limites de l’API viennent de sa documentation, consultée le 10 octobre 2026.
Ce que vous allez apprendre
- Ce que permet l’API de recherche de l’État, et ses limites
- Un script Python complet et testé (bibliothèque standard uniquement)
- Comment il contrôle les numéros avant l’appel
- Comment il gère la limite de débit et le code HTTP 429
- Comment lire les résultats, et ce que signifie « introuvable »
L’API utilisée
L’API Recherche d’entreprises est l’API gratuite de l’État qui alimente l’Annuaire des Entreprises. Selon sa documentation :
- ni clé ni compte ;
- au maximum 7 requêtes par seconde par adresse IP, et 30 par seconde par ASN ; au-delà, réponse HTTP 429 avec un en-tête
Retry-After; - ce débit est un maximum, pas une garantie ;
- un User-Agent explicite est recommandé ;
- les entreprises non diffusibles ne sont pas renvoyées.
Pour le contexte, voir API SIREN gratuite : les options officielles.
L’entrée
Un fichier CSV, un SIREN par ligne, espaces acceptés :
441639465
794598813
4416 3946
552100554
Le script
Enregistrez-le sous check_sirens.py. Il n’utilise que la bibliothèque standard de Python (3.10 ou plus).
import csv
import json
import sys
import time
import urllib.error
import urllib.request
from datetime import datetime, timezone
API = "https://recherche-entreprises.api.gouv.fr/search?q={}"
HEADERS = {"User-Agent": "my-company-siren-check/1.0 (+https://example.com/contact)"}
def luhn_ok(siren: str) -> bool:
if len(siren) != 9 or not siren.isdigit():
return False
total = 0
for i, ch in enumerate(reversed(siren)):
d = int(ch) * (2 if i % 2 else 1)
total += d - 9 if d > 9 else d
return total % 10 == 0
def lookup(siren: str) -> dict | None:
req = urllib.request.Request(API.format(siren), headers=HEADERS)
for attempt in range(5):
try:
with urllib.request.urlopen(req, timeout=20) as r:
data = json.load(r)
return next((c for c in data["results"] if c["siren"] == siren), None)
except urllib.error.HTTPError as e:
if e.code == 429:
time.sleep(int(e.headers.get("Retry-After", "1")))
continue
raise
raise RuntimeError(f"{siren}: still rate-limited after 5 tries")
def main(src: str, dst: str) -> None:
with open(src, newline="", encoding="utf-8") as f:
sirens = [row[0].replace(" ", "") for row in csv.reader(f) if row]
with open(dst, "w", newline="", encoding="utf-8") as f:
out = csv.writer(f)
out.writerow(["siren", "result", "name", "status", "closed_on", "checked_at"])
for siren in sirens:
checked = datetime.now(timezone.utc).isoformat(timespec="seconds")
if not luhn_ok(siren):
out.writerow([siren, "invalid_number", "", "", "", checked])
continue
company = lookup(siren)
time.sleep(0.25) # stay well under 7 requests per second
if company is None:
out.writerow([siren, "not_found_in_public_data", "", "", "", checked])
continue
status = {"A": "active", "C": "ceased"}.get(company["etat_administratif"], company["etat_administratif"])
out.writerow([siren, "found", company["nom_complet"], status, company.get("date_fermeture") or "", checked])
if __name__ == "__main__":
main(sys.argv[1], sys.argv[2])
Lancez-le :
python check_sirens.py sirens.csv results.csv
Remplacez l’adresse de contact du User-Agent par celle de votre site.
Ce qu’il fait, étape par étape
- Nettoie chaque numéro : retire les espaces.
- Le contrôle localement : neuf chiffres, et selon l’INSEE un neuvième chiffre de contrôle (Luhn). Un numéro invalide est marqué
invalid_numbersans appel à l’API. Voir les formats SIREN, SIRET et TVA. - Cherche le numéro dans l’API et ne garde que le résultat dont le
sirencorrespond exactement. - Attend 0,25 seconde entre deux appels, environ 4 requêtes par seconde, bien sous les 7 documentées.
- Gère le code HTTP 429 : attend le nombre de secondes de
Retry-After, puis réessaie, jusqu’à cinq fois. - Écrit une ligne par numéro, avec l’heure de vérification.
Le résultat
Voici ce que le script a renvoyé le 10 octobre 2026 :
| siren | result | name | status | closed_on | checked_at |
|---|---|---|---|---|---|
| 441639465 | found | RENAULT (RENAULT) | active | 10 oct. 2026, 12:57:01 UTC | |
| 794598813 | found | DOCTOLIB | active | 10 oct. 2026, 12:57:02 UTC | |
| 44163946 | invalid_number | 10 oct. 2026, 12:57:02 UTC | |||
| 552100554 | found | PEUGEOT SA | ceased | 16 janv. 2021 | 10 oct. 2026, 12:57:02 UTC |
(Le CSV écrit les dates au format ISO ; elles sont écrites ici en toutes lettres.)
- PEUGEOT SA est cessée depuis le 16 janvier 2021 : si elle figurait parmi vos fournisseurs actifs, c’est la ligne qui compte.
- 4416 3946 est invalide : le SIREN de Renault avec un chiffre manquant n’a que huit chiffres, donc aucun appel à l’API. Un chiffre modifié serait arrêté de la même façon par le chiffre de contrôle.
- Chaque ligne porte son heure de vérification : un statut sans date est une opinion ; avec une date, c’est un fait que vous pouvez montrer.
« Introuvable »
not_found_in_public_data signifie que l’API n’a renvoyé aucune entreprise avec ce SIREN exact. Cela ne prouve pas que l’entreprise n’existe pas : l’API écarte les entreprises non diffusibles, souvent des entrepreneurs individuels. Confiez ces lignes à une personne, qui demandera un justificatif. Voir les entreprises non diffusibles.
Pour aller plus loin
- Ajoutez les colonnes utiles, comme l’adresse du siège (
siege) ou le code d’activité : affichez un résultat en JSON pour voir les champs. - Lancez-le à intervalle régulier, chaque mois ou avant les renouvellements, et comparez avec le passage précédent.
- Gardez les fichiers de sortie : c’est votre trace de ce que vous avez vérifié, et quand.
- Sur une IP de cloud partagée, attendez-vous à plus de lenteur, à cause de la limite par réseau.
Pour les entreprises cessées, voir client ou fournisseur radié ou cessé : que faire ; pour le reste du fichier, nettoyer son CRM avec les registres officiels.
L’API Fuentio répondra à la même question pour la France et l’Espagne dans un même format, avec la source et l’heure de vérification sur chaque ligne. Elle n’est pas encore ouverte : inscrivez-vous ci-dessous pour être prévenu.
Voyez ce que nous couvrons en France et en Espagne.
Limites. Les limites de l’API viennent de sa documentation, consultée le 10 octobre 2026 ; elles peuvent changer, vérifiez-les avant un gros traitement. Le résultat montré est celui du 10 octobre 2026. Le script est un exemple : testez-le sur vos données et respectez les conditions de l’API. Ceci n’est pas un conseil juridique.
Questions fréquentes
Peut-on vérifier gratuitement beaucoup de SIREN d’un coup ?
Oui. L’API de recherche de l’État est gratuite et sans clé ; le script ci-dessus vérifie un CSV en respectant sa limite.
À quelle vitesse peut-on appeler l’API ?
Au maximum 7 requêtes par seconde par adresse IP, et 30 par seconde par ASN, selon sa documentation. Le script en fait environ 4.
Pourquoi un SIREN valide est-il « introuvable » ?
L’entreprise est peut-être non diffusible : l’API ne les renvoie pas. Demandez un justificatif à l’entreprise.
Faut-il contrôler les SIREN avant l’appel ?
Ce n’est pas obligatoire, mais le contrôle de Luhn attrape gratuitement la plupart des fautes de frappe.
Sources
- API Recherche d’entreprises, documentation (consultée le 10 octobre 2026) : recherche-entreprises.api.gouv.fr
- INSEE, définition du numéro SIREN : insee.fr
- Annuaire des Entreprises : annuaire-entreprises.data.gouv.fr
