Utiliser l’API CAPTCHA avec Selenium en C#
Appelez solvethree avec HttpClient, attendez qu'une tâche soit prête, puis placez solution.token dans le champ CAPTCHA de votre application. Chrome doit utiliser le même proxy et l'identité de navigateur renvoyée avant d'ouvrir la page cible.
L'exemple ci-dessous utilise .NET 8 et Selenium Chrome pour envoyer un formulaire que vous contrôlez. Il s'agit d'une intégration REST directe, et non d'un SDK C# officiel ou d'un plugin Selenium.
Sur cette page
Préparer le projet et la cible
- Utilisez un projet console .NET 8 avec ses directives using implicites par défaut activées. Ajoutez les packages NuGet
Selenium.WebDriveretSelenium.Support, tous deux en version4.52.0. - Installez Chrome localement. Selenium Manager fournit un pilote Chrome compatible.
- Assurez-vous que le nom d'hôte cible dispose d'un profil de site actif accessible à votre espace de travail. Envoyer un nom d'hôte et une action n'en crée pas ; suivez d'abord les instructions de configuration du profil de site.
- Utilisez un proxy autorisé par adresse IP, sans identifiants dans son URL. L'exemple transmet ce même proxy à solvethree et à Chrome.
| Variable | Valeur à fournir |
|---|---|
SOLVETHREE_API_KEY | La clé API de votre espace de travail. Conservez-la sur la machine de confiance qui exécute l'automatisation, et non dans la page. |
SOLVETHREE_PROXY | L'URL du proxy autorisé par adresse IP, utilisé à la fois pour la résolution et pour l'envoi depuis le navigateur. |
TARGET_URL | L'URL complète de la page du formulaire de votre application. L'exemple en extrait le nom d'hôte pour le champ site de la tâche. |
Remplacez la valeur login de action dans l'exemple si votre intégration utilise une autre action. L'exemple repose sur la valeur par défaut de recaptchaType, enterprise-v3 ; la requête de tâche n'a pas besoin de champ type ou url.
Créer la tâche et envoyer le formulaire
La fonction auxiliaire d'API s'authentifie avec la clé de votre espace de travail et rejette les réponses HTTP qui n'indiquent pas une réussite avant d'analyser un contenu de réussite. Le programme crée une tâche, interroge son identifiant tant que son statut est pending ou solving, et ne démarre Chrome qu'une fois la tâche au statut ready.
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json.Nodes;
var key = Environment.GetEnvironmentVariable("SOLVETHREE_API_KEY")
?? throw new Exception("Set SOLVETHREE_API_KEY");
var proxy = Environment.GetEnvironmentVariable("SOLVETHREE_PROXY")
?? throw new Exception("Set SOLVETHREE_PROXY");
using var http = new HttpClient { Timeout = TimeSpan.FromSeconds(30) };
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", key);
using var deadline = new CancellationTokenSource(TimeSpan.FromSeconds(180));
async Task<JsonObject> Api(HttpMethod method, string path, JsonObject? body = null)
{
using var request = new HttpRequestMessage(method, "https://api.solvethree.com/v1" + path);
if (body is not null)
request.Content = new StringContent(body.ToJsonString(), Encoding.UTF8, "application/json");
using var response = await http.SendAsync(request, deadline.Token);
response.EnsureSuccessStatusCode();
return JsonNode.Parse(await response.Content.ReadAsStringAsync(deadline.Token))!.AsObject();
}
var requestId = Guid.NewGuid().ToString(); // Save with these inputs for recovery.
var input = new JsonObject {
["site"] = new Uri(Environment.GetEnvironmentVariable("TARGET_URL") ?? throw new Exception("Set TARGET_URL")).Host, ["action"] = "login",
["proxy"] = proxy, ["requestId"] = requestId
};
var task = await Api(HttpMethod.Post, "/tasks?waitMs=0", input);
while (task["status"]!.GetValue<string>() is "pending" or "solving")
{
var id = Uri.EscapeDataString(task["id"]!.GetValue<string>());
task = await Api(HttpMethod.Get, "/tasks/" + id + "?waitMs=15000");
if (task["status"]!.GetValue<string>() is "pending" or "solving")
await Task.Delay(1000, deadline.Token);
}
if (task["status"]!.GetValue<string>() != "ready")
throw new Exception("Task failed: " + task["errorCode"]?.GetValue<string>()
+ ": " + task["error"]?.GetValue<string>());
var solution = task["solution"]!.AsObject();
// Use solution["token"], ["userAgent"] and ["secChUa"] with the original proxy.
Console.WriteLine("Ready task: " + task["id"]!.GetValue<string>());
var target = Environment.GetEnvironmentVariable("TARGET_URL") ?? throw new Exception("Set TARGET_URL");
if (!string.IsNullOrEmpty(new Uri(proxy).UserInfo)) throw new Exception("Use an IP-allowlisted proxy");
var options = new ChromeOptions();
options.AddArgument("--proxy-server=" + proxy);
options.AddArgument("--user-agent=" + solution["userAgent"]!.GetValue<string>());
using var browser = new ChromeDriver(options);
browser.ExecuteCdpCommand("Network.enable", new Dictionary<string, object>());
browser.ExecuteCdpCommand("Network.setExtraHTTPHeaders", new Dictionary<string, object> {
["headers"] = new Dictionary<string, object> { ["sec-ch-ua"] = solution["secChUa"]!.GetValue<string>() }
});
browser.Navigate().GoToUrl(target);
var wait = new WebDriverWait(browser, TimeSpan.FromSeconds(20));
var field = wait.Until(driver => driver.FindElement(By.Name("g-recaptcha-response")));
browser.ExecuteScript("arguments[0].value=arguments[1]; arguments[0].dispatchEvent(new Event('input',{bubbles:true}));",
field, solution["token"]!.GetValue<string>());
browser.FindElement(By.CssSelector("button[type=submit]")).Click();
wait.Until(driver => driver.FindElement(By.Id("success"))); // Your application's success marker.Le délai d'attente HTTP de 30 secondes, l'échéance de 180 secondes pour l'API et l'attente Selenium de 20 secondes sont des paramètres de cet exemple, et non des garanties de délai du service. Adaptez-les à la politique de délai d'attente de votre application.
Adapter la transmission à votre application
- 1.
Conserver ensemble le proxy et l'identité renvoyée
ChromeOptions applique le proxy d'origine et
solution.userAgent. Les commandes CDP activent le réseau et définissentsec-ch-uaà partir desolution.secChUaavant la navigation. Respectez cet ordre ; n'ouvrez pas d'abord la page pour modifier l'identité ensuite. - 2.
Écrire le jeton à l'endroit où l'application le lit
L'exemple repère un champ nommé
g-recaptcha-response, lui affectesolution.tokenet déclenche un événement input. Remplacez ce mécanisme de transmission si votre application lit le jeton ailleurs. Remplir un champ n'est utile que si la requête sortante de l'application contient effectivement sa valeur. - 3.
Remplacer les sélecteurs d'envoi et de réussite
L'exemple clique sur
button[type=submit]et attend un élément dont l'identifiant estsuccess. Utilisez les sélecteurs de votre application réelle et choisissez un indicateur de réussite qui confirme que l'opération envoyée a abouti, et pas simplement qu'un clic a eu lieu sur le bouton.
Une tâche prête signifie qu'une solution est disponible. La vérification après l'envoi est distincte : la cible décide toujours si elle accepte la requête de l'application.
Gérer les échecs sans créer de tâches inutiles
- La fonction auxiliaire d'API lève une exception à la réception d'une réponse HTTP.
Inspectez le statut HTTP et la réponse d'erreur. Ce cas est différent d'une tâche qui atteint le statut
failed.Essayez ceci : Corrigez le problème de requête ou d'authentification signalé avant de réessayer. Ne renvoyez pas continuellement les mêmes données invalides.
- La tâche atteint le statut
failed. Lisez
errorCodeeterror;site-unreachableest une erreur de tâche possible.Essayez ceci : Arrêtez d'interroger cette tâche et traitez la cause signalée. Les résolutions échouées sont remboursées.
- La tâche est prête, mais la cible rejette l'envoi.
Inspectez d'abord la requête sortante de l'application : contient-elle
solution.token, plutôt que l'identifiant de la tâche ou un ancien jeton ? Vérifiez ensuite le proxy, l'agent utilisateur, les indications client et l'URL cible.Essayez ceci : Corrigez la transmission du jeton ou l'incohérence d'identité avant de payer une autre résolution.
- Selenium dépasse le délai d'attente après le clic sur le bouton d'envoi.
Inspectez la page et la réponse de l'application. Le sélecteur
successest un élément de l'exemple, et non un signal universel d'acceptation.Essayez ceci : Remplacez-le par la condition de réussite réelle de votre application, ou traitez le rejet renvoyé par l'application.
L'exemple génère un requestId, mais ne l'enregistre pas pour vous. Enregistrez-le avec les données d'entrée exactes de la tâche avant la création si vous devez pouvoir récupérer la tâche après un dépassement de délai. Si la création dépasse le délai d'attente, renvoyez les mêmes données avec ce même identifiant pour récupérer la tâche existante ; ne générez pas un nouvel identifiant simplement parce que la réponse a été perdue. Réutiliser un identifiant avec des données différentes provoque un conflit. Si vous disposez déjà de l'identifiant de la tâche, récupérez plutôt cette tâche.
Sources et référence de l’API
Lancez votre première tâche.
Démarrez avec $5 de crédit dans votre espace de travail.