URL → Markdown
Convert company sites into clean markdown for enrichment, scoring, and LLM pipelines.
Most enrichment scripts fail on the modern web: Cloudflare, dynamic rendering, and geo quirks. browser.city gives you a stealth-by-default extraction primitive so your pipeline has fewer holes.
Convert company sites into clean markdown for enrichment, scoring, and LLM pipelines.
Avoid bot walls that break “simple” enrichment scripts. Stealth defaults mean fewer missing fields.
Move from a list of leads to a pipeline: batch endpoints + concurrency with predictable outputs.
When a site needs clicks or login, switch to Sessions (Playwright connect) or Humanized REST tools.
Enrichment is sensitive. A zero-logs stance helps you keep customer and prospect data out of vendor systems.
Keep your enrichment logic in your stack. browser.city provides the browsing/extraction primitive, nothing else.
Fetch a lead’s website as markdown, then extract signals like emails, social links, pricing, and product keywords.
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", markdown: true }),}).then((r) => r.json());const md = String(res.content ?? "");const emails = Array.from( md.matchAll(/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/gi), (m) => m[0],);console.log({ emails: Array.from(new Set(emails)) });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", "markdown": True},).json()md = str(res.get("content", ""))emails = sorted(set(re.findall(r"[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}", md, re.I)))print({"emails": emails})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", markdown = true });var json = await res.Content.ReadFromJsonAsync<RequestResponse>() ?? throw new Exception("bad response");var md = json.content ?? "";var matches = Regex.Matches(md, "[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}", RegexOptions.IgnoreCase);var emails = matches.Select(m => m.Value).Distinct().OrderBy(x => x).ToArray();Console.WriteLine(string.Join("\n", emails));public record RequestResponse(string? content);import java.net.URI;import java.net.http.*;import java.util.*;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\",\"markdown\":true}")) .build();var res = http.send(req, HttpResponse.BodyHandlers.ofString());var json = res.body();var md = extractField(json, "content");var p = Pattern.compile("[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}", Pattern.CASE_INSENSITIVE);var m = p.matcher(md);var emails = new TreeSet<String>();while (m.find()) emails.add(m.group());System.out.println(emails);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.