Raccourcir une URL en Python tient en une seule requête HTTP POST. Vous envoyez votre lien long à l'API d'un raccourcisseur avec la bibliothèque requests, vous passez votre clé API en tant que jeton Bearer, et vous lisez le lien court dans la réponse JSON. Le tout tient en environ cinq lignes, et le reste de ce guide couvre ce qu'il faut ajouter une fois que vous faites cela pour de vrai : gestion des erreurs, idempotence, traitement en masse et asynchrone.
C'est la version pour développeurs du guide général sur comment raccourcir une URL - celui-là couvre le tableau de bord et le flux navigateur, celui-ci est du code que vous pouvez coller dans un script. Les endpoints et noms de champs ci-dessous utilisent l'API Elido, mais la structure (envoyer une destination en POST, récupérer une URL courte en retour) est la même chez la plupart des raccourcisseurs modernes, donc les modèles se transposent.
Partez du tour d'horizon de l'API gratuite de raccourcissement d'URL si vous n'avez pas encore choisi de service - il détaille la structure des requêtes, le modèle d'authentification, et les limites du forfait gratuit sur lesquelles s'appuie cet article.
La méthode la plus rapide : un seul POST avec requests
Installez requests, placez votre clé API dans une variable d'environnement, et envoyez un POST avec l'URL de destination vers l'endpoint des liens :
import os
import requests
resp = requests.post(
"https://api.elido.app/v1/links",
headers={"Authorization": f"Bearer {os.environ['ELIDO_API_KEY']}"},
json={"destination_url": "https://example.com/a-very-long-path?with=params"},
timeout=10,
)
resp.raise_for_status()
print(resp.json()["short_url"]) # -> https://s.elido.me/ab12cd
Trois détails rendent ce code prêt pour la production plutôt qu'un simple jouet. La clé API vient de l'environnement, jamais d'une valeur écrite en dur dans le code source. timeout est défini, pour qu'une connexion bloquée échoue rapidement au lieu de rester en attente indéfiniment. Et raise_for_status() transforme un code 4xx ou 5xx en exception que vous pouvez intercepter, plutôt que de laisser un appel échoué ressembler à un succès.
La réponse est du JSON. Lisez short_url pour obtenir le lien final ; la plupart des raccourcisseurs renvoient aussi un id que vous pouvez conserver si vous prévoyez de modifier ou d'expirer le lien plus tard.
Gérer correctement les erreurs et les limites de débit
Le chemin nominal tient en cinq lignes. Un script qui tourne sans surveillance doit survivre aux cas moins heureux : un 5xx transitoire, un 429 quand vous allez trop vite, un accroc réseau. Encapsulez l'appel pour qu'il relance sur les erreurs qui valent la peine d'être relancées et abandonne sur celles qui ne réussiront jamais.
import os
import time
import requests
def shorten(destination: str, *, retries: int = 3) -> str:
headers = {"Authorization": f"Bearer {os.environ['ELIDO_API_KEY']}"}
for attempt in range(retries):
resp = requests.post(
"https://api.elido.app/v1/links",
headers=headers,
json={"destination_url": destination},
timeout=10,
)
if resp.status_code == 429:
time.sleep(int(resp.headers.get("Retry-After", 2)))
continue
if resp.status_code >= 500:
time.sleep(2 ** attempt) # exponential backoff
continue
resp.raise_for_status() # 4xx other than 429 -> raise
return resp.json()["short_url"]
raise RuntimeError(f"shorten failed after {retries} attempts")
Un 401 ou un 403 ne se corrigera jamais tout seul en réessayant, donc ces cas tombent dans raise_for_status() et arrêtent le script. Un 429 respecte l'en-tête Retry-After renvoyé par l'API. Un 5xx recule de façon exponentielle. Le dossier approfondi sur les limites de débit et l'idempotence explique pourquoi relancer aveuglément est le meilleur moyen de transformer une panne en deux pannes.
Envoyer une Idempotency-Key pour que les retries ne créent pas de doublons
Voici le bug subtil de la boucle de retry ci-dessus. Si un POST réussit côté serveur mais que la réponse se perd sur le chemin du retour, votre code voit un timeout, relance la requête, et crée un second lien court pour la même URL. Une clé d'idempotence corrige ce problème : envoyez une clé stable et unique avec chaque requête logique, et l'API renvoie le lien original en cas de répétition au lieu d'en créer un nouveau.
import uuid
key = str(uuid.uuid4()) # one key per URL you want shortened once
resp = requests.post(
"https://api.elido.app/v1/links",
headers={
"Authorization": f"Bearer {os.environ['ELIDO_API_KEY']}",
"Idempotency-Key": key,
},
json={"destination_url": "https://example.com/launch"},
timeout=10,
)
Générez la clé une seule fois par URL et réutilisez-la à travers les retries de cette même URL - pas une clé par tentative. Conservez-la avec l'URL si le lot entier risque d'être relancé. C'est l'habitude la plus importante quand vous passez de raccourcir une seule URL à en raccourcir une liste, et elle est intégrée dans les API et SDK exactement pour cette raison.
Raccourcir des URL en masse
Avec un shorten() sécurisé en main, un lot devient une simple boucle - mais une boucle qui respecte la limite de débit et ne perd pas la correspondance entre entrée et sortie :
urls = [
"https://example.com/spring-sale",
"https://example.com/newsletter",
"https://example.com/docs/getting-started",
]
results = {}
for url in urls:
try:
results[url] = shorten(url)
except Exception as err: # log and keep going; one bad URL should not sink the batch
results[url] = f"ERROR: {err}"
for original, short in results.items():
print(f"{short}\t{original}")
Conserver le résultat dans un dictionnaire indexé par l'URL d'origine rend un échec partiel visible et rejouable, plutôt qu'un trou silencieux. Pour quelques centaines de liens, cette version séquentielle suffit amplement. Pour des milliers, la latence des allers-retours s'accumule, et c'est là que l'asynchrone justifie sa place.
Passer à l'échelle avec httpx en asynchrone
Quand le lot est volumineux, le goulot d'étranglement est l'attente réseau, pas Python. Un client asynchrone comme httpx envoie de nombreuses requêtes en parallèle tout en maintenant un plafond sur le nombre de requêtes en vol, de sorte que vous saturiez la connexion sans déclencher la limite de débit.
import asyncio
import os
import httpx
async def shorten_all(urls: list[str], concurrency: int = 10) -> dict[str, str]:
headers = {"Authorization": f"Bearer {os.environ['ELIDO_API_KEY']}"}
limit = asyncio.Semaphore(concurrency)
out: dict[str, str] = {}
async with httpx.AsyncClient(timeout=10) as client:
async def one(url: str) -> None:
async with limit:
r = await client.post(
"https://api.elido.app/v1/links",
headers=headers,
json={"destination_url": url},
)
out[url] = r.json()["short_url"]
await asyncio.gather(*(one(u) for u in urls))
return out
# asyncio.run(shorten_all(my_urls))
Le Semaphore(10) est toute l'astuce : il plafonne les requêtes concurrentes à dix, pour que vous alliez vite sans marteler l'API jusqu'à provoquer des 429. Ajustez-le à la limite documentée de votre forfait. Pour la structure complète des requêtes, les noms de champs et les limites actuelles, les docs de l'API font référence, et solutions pour développeurs propose les SDK si vous préférez ne pas coder le client à la main.
Quelle approche choisir
Adaptez l'outil à la taille du travail. Un seul lien dans un script : l'appel requests en cinq lignes. Une tâche fiable qui tourne sur planification : la version avec retry et idempotence. Un lot ponctuel de quelques centaines : la boucle séquentielle. Des dizaines de milliers avec un délai serré : httpx avec un semaphore.
Quelle que soit votre option, gardez la clé dans l'environnement, définissez un timeout, et envoyez une clé d'idempotence sur tout ce qui pourrait être relancé. Ces trois habitudes font toute la différence entre un extrait de code qui fait une démo et un script que vous pouvez laisser tourner.
Lire la série pilier
Cet article appartient au cluster engineering. Le point de départ est le guide de l'API gratuite de raccourcissement d'URL pour la structure des endpoints et l'authentification, puis le dossier limites de débit et idempotence pour bien se comporter sous charge. La référence vivante reste les docs de l'API.
À lire aussi sur le blog
Questions fréquentes
Comment raccourcir une URL en Python ?
Envoyez une requête HTTP POST à l'API d'un raccourcisseur d'URL avec la bibliothèque requests, en passant votre URL longue dans le corps JSON et votre clé API en tant que jeton Bearer, puis lisez le lien court dans la réponse JSON. Cela tient en environ cinq lignes : construire les en-têtes, envoyer un POST avec l'URL de destination vers l'endpoint des liens, et afficher response.json()['short_url'].
Puis-je raccourcir une URL en Python sans bibliothèque externe ?
Oui. Le module urllib.request de la bibliothèque standard peut envoyer un POST JSON sans rien installer, ce qui est pratique dans un environnement verrouillé. C'est plus verbeux que requests - vous encodez le corps vous-même, définissez les en-têtes manuellement, et lisez la réponse à la main - mais cela ne nécessite aucun pip install.
Comment raccourcir plusieurs URL à la fois en Python ?
Parcourez la liste et envoyez un POST pour chacune, mais ajoutez une Idempotency-Key par URL pour qu'un retry ne crée jamais de doublon, et respectez la limite de débit de l'API en reculant sur un code HTTP 429. Pour de gros lots, un client asynchrone comme httpx avec un semaphore borné raccourcit des milliers d'URL en parallèle plutôt qu'une par une.
Pourquoi ma requête de raccourcissement d'URL en Python renvoie-t-elle 401 ?
Un 401 signifie que la clé API est absente ou incorrecte dans l'en-tête Authorization. Vérifiez que vous envoyez exactement 'Authorization: Bearer YOUR_API_KEY', que la clé n'a pas été révoquée, et que vous l'avez chargée depuis une variable d'environnement plutôt que collée depuis une clé expirée. Un 403, en revanche, signifie que la clé est valide mais ne dispose pas de la portée nécessaire pour cette action.
Essayer Elido
Collez une URL, obtenez un lien court
Sans inscription. Lien actif 30 jours. Inscrivez-vous pour le garder pour toujours.
Gratuit, sans inscription · 2 par jour