One Request = One Signal
Use the Request API to turn a product URL into clean HTML or markdown. No browser runtime, no Playwright harness.
Build hobby projects that survive real anti-bot systems. Start with the Request API (URL → markdown), then add proxies, CAPTCHA solving, and batching when your watch list grows.
Use the Request API to turn a product URL into clean HTML or markdown. No browser runtime, no Playwright harness.
Realistic TLS + browser fingerprints help you avoid the “403 after 3 requests” problem common in hobbyist scripts.
Retailers and marketplaces behave differently per geo and network. Choose proxy type and location when you need it.
Handle reCAPTCHA, hCaptcha, and Turnstile without wiring a third-party service into your scripts.
When your “watch list” becomes a catalog, use batch endpoints for higher throughput and fewer round-trips.
Per-minute pricing and a free tier make it practical for side projects and hobby monitoring without surprises.
Fetch a product page as markdown and parse a price. For multiple URLs, switch to batch endpoints and run this in a scheduler.
const apiKey = process.env.BROWSERCITY_API_KEY!;const opts = { method: "POST", headers: { Authorization: `Bearer ${apiKey}` } };const res = await fetch("https://api.browser.city/v1/requests", { ...opts, body: JSON.stringify({ url: "https://example.com/product", markdown: true }),}).then((r) => r.json());const md = String(res.content ?? "");const match = md.match(/\$([0-9,.]+)/);if (!match) throw new Error("price not found");console.log({ price: match[1] });import osimport reimport requestsapi_key = os.environ["BROWSERCITY_API_KEY"]res = requests.post( "https://api.browser.city/v1/requests", headers={"Authorization": f"Bearer {api_key}"}, json={"url": "https://example.com/product", "markdown": True},).json()md = str(res.get("content", ""))m = re.search(r"\$([0-9,.]+)", md)if not m: raise RuntimeError("price not found")print({"price": m.group(1)})using System.Net.Http.Headers;using System.Net.Http.Json;using System.Text.RegularExpressions;var apiKey = Environment.GetEnvironmentVariable("BROWSERCITY_API_KEY")!;var http = new HttpClient();http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);var res = await http.PostAsJsonAsync( "https://api.browser.city/v1/requests", new { url = "https://example.com/product", markdown = true });var json = await res.Content.ReadFromJsonAsync<RequestResponse>() ?? throw new Exception("bad response");var md = json.content ?? "";var m = Regex.Match(md, "\\$([0-9,.]+)");if (!m.Success) throw new Exception("price not found");Console.WriteLine(m.Groups[1].Value);public record RequestResponse(string? content);import java.net.URI;import java.net.http.*;import java.util.regex.*;var apiKey = System.getenv("BROWSERCITY_API_KEY");var auth = "Bearer " + apiKey;var http = HttpClient.newHttpClient();var req = HttpRequest.newBuilder() .uri(URI.create("https://api.browser.city/v1/requests")) .header("Authorization", auth) .POST(HttpRequest.BodyPublishers.ofString( "{\"url\":\"https://example.com/product\",\"markdown\":true}")) .build();var res = http.send(req, HttpResponse.BodyHandlers.ofString());var json = res.body();var md = extractField(json, "content");var m = Pattern.compile("\\$([0-9,.]+)").matcher(md);if (!m.find()) throw new RuntimeException("price not found");System.out.println(m.group(1));static String extractField(String json, String key) { // Use a proper JSON parser in production. This is intentionally minimal. var i = json.indexOf("\"" + key + "\""); if (i < 0) return ""; var start = json.indexOf('"', i + key.length() + 2); var end = json.indexOf('"', start + 1); return (start >= 0 && end > start) ? json.substring(start + 1, end) : "";} Free tier. No credit card. Full stealth from day one.