Clutch.co listet mehr als 150.000 Dienstleister aus IT, Marketing, Design und Entwicklung, und jedes Unternehmensprofil enthält die strukturierten B2B-Daten, die eine Lead-Generierungspipeline, ein Wettbewerbsforschungs-Dashboard oder eine Marktstudie tatsächlich benötigt: Unternehmensname, Sternebewertung, Anzahl der Bewertungen, Mindestprojektgröße, Stundensatzspanne, Standort und ein Link zum vollständigen Profil. Der Haken: Clutch ist hinter starkem Bot-Schutz verborgen, sodass eine einfache HTTP-Anfrage selten überhaupt die Listing-Seite erreicht.
Dieser Leitfaden zeigt, wie man zuverlässig einen Python-Scraper für Clutch.co aufbaut. Man erstellt ein kleines, ausführbares Skript, das eine gerenderte Kategorieseite über die Crawling API abruft, jede Unternehmenskarte mit BeautifulSoup parst und saubere strukturierte Zeilen schreibt. Die gesamte Anleitung beschränkt sich auf öffentliche Unternehmens-Listing-Daten, und der Abschnitt zur Rechtslage am Ende ist kein Boilerplate, also lesen Sie ihn, bevor Sie dieses Skript auf ein echtes Volumen ansetzen.
Was Sie bauen werden
Ein Python-Skript, das eine öffentliche Clutch.co-Kategorie-URL nimmt, das gerenderte HTML über die Crawling API abruft und für jedes Unternehmen auf der Seite einen strukturierten Datensatz extrahiert. Als durchgehendes Beispiel verwenden wir das IT-Services-Verzeichnis und ziehen diese Felder aus jeder Karte:
- Unternehmensname der eingetragene Geschäftsname des Anbieters.
- Bewertung die aggregierte Sternebewertung auf der Karte.
- Anzahl der Bewertungen wie viele Kundenbewertungen diese Bewertung stützen.
- Mindestprojektgröße das kleinste Engagement, das der Anbieter annimmt, zum Beispiel „$5.000+".
- Stundensatz die angegebene Stundensatzspanne, zum Beispiel „$50 - $99 / Std.".
- Standort die primäre Stadt oder Region des Anbieters.
- Profil-URL der Link zum vollständigen Clutch-Profil des Unternehmens.
Warum eine einfache Anfrage bei Clutch.co scheitert
Wenn man eine Clutch.co-Kategorie-URL mit einem einfachen HTTP-Client anfragt, erhält man in der Regel kein Listing zurück. Clutch betreibt aggressiven Bot-Schutz, und eine Datacenter-IP, die eine offensichtlich automatisierte Anfrage stellt, wird herausgefordert oder erhält ein 403, bevor irgendwelche Unternehmensdaten ankommen. Selbst wenn eine Anfrage durchschlüpft, werden Teile der Seite clientseitig befüllt, sodass das rohe HTML genau die Karten fehlen kann, wegen derer man dort ist.
Ein funktionierender Clutch-Scraper benötigt also zwei Dinge in einer Anfrage: einen Browser, der die Seite tatsächlich rendert, und eine IP, die die Plattform als echten Besucher liest. Man kann das selbst mit einem Headless-Browser und einem Pool rotierender Residential-Proxies zusammenstellen, aber das Zusammenfügen und Gesundhalten dieser Komponenten ist der Großteil der Arbeit. Die Crawling API fasst beides in einem einzigen Aufruf zusammen: Man sendet ihr die URL mit einem JavaScript-Token, sie rendert die Seite hinter einer vertrauenswürdigen Residential-IP und gibt fertiges HTML zurück, das man parsen kann.
Crawlbase bietet zwei Token-Typen an. Der normale Token ruft statisches HTML ab; der JavaScript-Token (JS) rendert die Seite zuerst in einem echten Browser und leitet die Anfrage durch rotierende Residential-IPs. Clutch ist gut verteidigt und teilweise clientseitig gerendert, also braucht man hier den JS-Token. Sie erhalten bis zu 20.000 kostenlose Anfragen, ohne Kreditkarte.
Voraussetzungen
Einige Dinge müssen vorab eingerichtet sein. Keines davon dauert lange.
Grundlegendes Python. Man sollte mit dem Schreiben und Ausführen eines Python-Skripts und dem Installieren von Paketen mit pip vertraut sein. Ist BeautifulSoup neu, deckt unser Leitfaden zur Verwendung von BeautifulSoup in Python die Parse-Grundlagen ab, die dieses Tutorial voraussetzt.
Python 3.8 oder höher. Version mit python --version prüfen. Wenn es nicht vorhanden ist, von python.org installieren und sicherstellen, dass Python im System-PATH vorhanden ist.
Ein Crawlbase-Konto und JS-Token. Anmelden, das Dashboard öffnen und den JavaScript-Token (JS) kopieren. Den Token wie ein Passwort behandeln: Er authentifiziert Anfragen, also aus der Versionskontrolle heraushalten.
Das Projekt einrichten
Eine virtuelle Umgebung erstellen, damit Projektabhängigkeiten isoliert bleiben, dann die benötigten Bibliotheken installieren.
python --version python -m venv clutch_env source clutch_env/bin/activate pip install crawlbase beautifulsoup4 pandas
Unter Windows die Umgebung mit clutch_env\Scripts\activate statt der source-Zeile aktivieren. Drei Abhängigkeiten übernehmen die Arbeit: crawlbase ist der offizielle Client für die Crawling API, beautifulsoup4 parst das zurückgegebene HTML, sodass man Felder per CSS-Selektor herausziehen kann, und pandas wandelt die gesammelten Zeilen am Ende in eine CSV-Datei um.
Schritt 1: Die gerenderte Kategorieseite abrufen
Zunächst die fertige Seite holen. Die CrawlingAPI-Klasse importieren, mit dem JS-Token initialisieren und die Kategorie-URL anfordern. Den Status vor dem Parsen zu prüfen hält Fehler laut statt still.
from crawlbase import CrawlingAPI api = CrawlingAPI({"token": "YOUR_CRAWLBASE_JS_TOKEN"}) def fetch_html(url): response = api.get(url, {"ajax_wait": "true", "page_wait": 5000}) if response["status_code"] == 200: return response["body"].decode("utf-8") print(f"Request failed: {response['status_code']}") return None if __name__ == "__main__": base_url = "https://clutch.co/it-services" html = fetch_html(base_url) print(html[:500] if html else "No HTML returned")
Die zwei Wait-Optionen sind wichtig für ein verteidigtes, teilweise clientseitig gerendertes Ziel wie dieses. ajax_wait weist die API an, auf das vollständige Laden asynchroner Inhalte zu warten, und page_wait hält nach dem Laden eine feste Anzahl Millisekunden an, damit spät gerenderte Karten erscheinen, bevor die Seite erfasst wird. Fünf Sekunden sind ein vernünftiger Ausgangswert; erhöhen, wenn Karten leer zurückkommen. Das Skript mit python scraper.py ausführen, und man sollte echtes Anbieter-Markup sehen, nicht die 403-Seite, die ein einfaches requests.get liefert. Das bestätigt, dass die Anfrage durchkommt, bevor man einen einzigen Selektor schreibt.
Clutch.co antwortet auf eine einfache Anfrage mit einem 403, also braucht man eine gerenderte Seite hinter einer vertrauenswürdigen IP in einem Aufruf. Die Crawling API nimmt einen JS-Token, führt die Seite in einem echten Browser aus, rotiert serverseitig durch Residential-IPs und gibt fertiges HTML zurück, sodass man keine eigene Headless-Flotte und keinen Proxy-Pool betreiben muss. Im kostenlosen Tarif zunächst auf das öffentliche IT-Services-Verzeichnis zeigen.
Schritt 2: Unternehmenskarten mit BeautifulSoup parsen
Mit fertigem HTML lädt man es in BeautifulSoup und zieht jeden Anbieter per Selektor heraus. Clutch strukturiert seine Listings in einer sich wiederholenden Struktur: Jeder Anbieter ist ein li.provider innerhalb von ul.providers__list, also wählt man alle Karten einmal aus und liest dann dieselben Felder von jeder. Die Live-Seite in den Entwicklerwerkzeugen des Browsers (meist F12) inspizieren, um die aktuellen Klassenamen zu bestätigen; die folgenden Selektoren entsprechen dem Layout zum Zeitpunkt der Erstellung.
import re from bs4 import BeautifulSoup def text_of(card, selector): el = card.select_one(selector) return re.sub(r"\s+", " ", el.get_text(strip=True)) if el else "N/A" def parse_html(html): soup = BeautifulSoup(html, "html.parser") data = [] companies = soup.select("ul.providers__list > li.provider") for company in companies: profile = company.select_one("h3.provider__title a") profile_url = profile["href"] if profile else "N/A" data.append({ "Company Name": text_of(company, "h3.provider__title"), "Rating": text_of(company, "span.sg-rating__number"), "Number of Reviews": text_of(company, "a.sg-rating__reviews"), "Min Project Size": text_of(company, "li.provider__highlights-item.min-project-size span"), "Hourly Rate": text_of(company, "li.provider__highlights-item.hourly-rate span"), "Location": text_of(company, "li.provider__highlights-item.location span.locality"), "Profile URL": profile_url, }) return data
Der Helfer text_of erledigt gleichzeitig zwei nützliche Dinge: Er gibt "N/A" zurück, wenn ein Element fehlt, statt bei einem .get_text()-Aufruf gegen nichts zu werfen, und er bereinigt mehrfache Leerzeichen mit re.sub(r"\s+", " ", ...), sodass eine Bewertungsanzahl wie "\n 128 reviews " sauber zurückkommt. Das macht die Extraktion widerstandsfähig, wenn ein Feld fehlt, was häufig vorkommt, da nicht jeder Anbieter eine Mindestprojektgröße oder einen Stundensatz angibt. Die Profil-URL wird aus dem href des Ankers gelesen statt aus seinem Text, daher wird sie separat behandelt.
Clutchs Klassenamen ändern sich ohne Vorankündigung. Die obigen Selektoren als Ausgangspunkt betrachten, nicht als Vertrag. Wenn ein Feld für jede Karte als "N/A" zurückkommt, ein Live-Listing in den Entwicklerwerkzeugen des Browsers erneut inspizieren und den Selektor aktualisieren. Periodische Selektor-Wartung ist für jeden Produktions-Scraper normal, kein Zeichen, dass etwas kaputt ist.
Schritt 3: Paginierung behandeln
Clutch listet Anbieter über viele Seiten, und es verwendet einen page-Abfrageparameter, um zwischen ihnen zu wechseln. Um ein ganzes Verzeichnis zu sammeln, durchläuft man die Seiten in einer Schleife, ruft jede über dieselbe Funktion ab und sammelt die Zeilen. Da alle Seiten dieselbe Kartenstruktur haben, funktioniert der bereits geschriebene Parser ohne Änderungen über alle hinweg.
import time def scrape_clutch_data(base_url, pages): all_data = [] for page in range(1, pages + 1): url = f"{base_url}?page={page}" html = fetch_html(url) if html: all_data.extend(parse_html(html)) time.sleep(3) return all_data
Das time.sleep(3) zwischen Anfragen ist bewusst. Die Drosselung verhindert, dass man Clutch in einer engen Schleife überflutet, was der schnellste Weg ist, gedrosselt zu werden, selbst wenn jede Anfrage über eine vertrauenswürdige IP gerendert wird. Mit einer Handvoll Seiten beginnen, während man bestätigt, dass die Selektoren halten, dann die Anzahl erhöhen, wenn die Ausgabe korrekt aussieht.
Schritt 4: Alles zusammenfügen und als CSV speichern
Jetzt den Abruf, das Parsen und die Paginierungsschleife zu einem ausführbaren Skript verbinden und dann die gesammelten Zeilen an pandas übergeben, um eine CSV zu schreiben. Eine flache CSV ist die portabelste Ausgabe für B2B-Daten: Sie öffnet sich in jeder Tabellenkalkulation, lässt sich in eine Datenbank laden und kann ohne weiteren Aufwand in einen CRM-Import eingespeist werden.
import re import time import pandas as pd from bs4 import BeautifulSoup from crawlbase import CrawlingAPI api = CrawlingAPI({"token": "YOUR_CRAWLBASE_JS_TOKEN"}) def fetch_html(url): response = api.get(url, {"ajax_wait": "true", "page_wait": 5000}) if response["status_code"] == 200: return response["body"].decode("utf-8") print(f"Request failed: {response['status_code']}") return None def text_of(card, selector): el = card.select_one(selector) return re.sub(r"\s+", " ", el.get_text(strip=True)) if el else "N/A" def parse_html(html): soup = BeautifulSoup(html, "html.parser") data = [] for company in soup.select("ul.providers__list > li.provider"): profile = company.select_one("h3.provider__title a") data.append({ "Company Name": text_of(company, "h3.provider__title"), "Rating": text_of(company, "span.sg-rating__number"), "Number of Reviews": text_of(company, "a.sg-rating__reviews"), "Min Project Size": text_of(company, "li.provider__highlights-item.min-project-size span"), "Hourly Rate": text_of(company, "li.provider__highlights-item.hourly-rate span"), "Location": text_of(company, "li.provider__highlights-item.location span.locality"), "Profile URL": profile["href"] if profile else "N/A", }) return data def scrape_clutch_data(base_url, pages): all_data = [] for page in range(1, pages + 1): html = fetch_html(f"{base_url}?page={page}") if html: all_data.extend(parse_html(html)) time.sleep(3) return all_data def main(): base_url = "https://clutch.co/it-services" data = scrape_clutch_data(base_url, pages=5) df = pd.DataFrame(data) df.to_csv("clutch_data.csv", index=False) print(f"Saved {len(data)} companies to clutch_data.csv") if __name__ == "__main__": main()
Das vollständige Skript mit python scraper.py ausführen, und es durchläuft fünf Seiten des IT-Services-Verzeichnisses, parst jeden Anbieter auf jeder Seite und schreibt eine CSV. base_url gegen eine andere öffentliche Kategorie austauschen, etwa https://clutch.co/agencies/digital, und pages anpassen, um die Tiefe zu steuern.
Wie die Ausgabe aussieht
Jede Zeile ist ein sauberer strukturierter Datensatz, bereit zum Öffnen in einer Tabellenkalkulation, zum Laden in eine Datenbank oder zum Einspeisen in einen CRM-Import. Hier ist ein Beispiel der vom Skript erzeugten Daten, zur Lesbarkeit als JSON dargestellt.
[ { "Company Name": "Lorem Software Group", "Rating": "4.9", "Number of Reviews": "128 reviews", "Min Project Size": "$25,000+", "Hourly Rate": "$50 - $99 / hr", "Location": "Austin, TX", "Profile URL": "https://clutch.co/profile/lorem-software-group" }, { "Company Name": "Ipsum Digital Labs", "Rating": "4.7", "Number of Reviews": "54 reviews", "Min Project Size": "$10,000+", "Hourly Rate": "$100 - $149 / hr", "Location": "London, England", "Profile URL": "https://clutch.co/profile/ipsum-digital-labs" } ]
Über Kategorien hinaus skalieren und nicht geblockt werden
Ein Verzeichnis ist eine Demo; ein echter Job läuft über viele Kategorien. Die Form bleibt dieselbe: eine Liste von Kategorie-URLs führen, scrape_clutch_data auf jeder ausführen und die Zeilen vor dem Schreiben der CSV zusammenführen. Der Parser funktioniert ohne Änderungen über alle hinweg. Clutch ist jedoch ein hartes kommerzielles Ziel, daher halten einige Gewohnheiten einen langen Durchlauf gesund.
- Anfragen drosseln. Seiten in einer engen Schleife zu hämmern ist der schnellste Weg, gedrosselt zu werden. Den Schlaf zwischen Anfragen beibehalten und einen großen Job über die Zeit verteilen statt ein ganzes Verzeichnis mit voller Geschwindigkeit zu crawlen.
- Auf Rotation setzen. Ein Pool von Residential-IPs verteilt Anfragen über viele echte Benutzeradressen, sodass keine einzelne ein Rate-Limit auslöst. Die Crawling API handhabt das; wenn man einen eigenen Stack aufbaut, ist das der Teil, den man richtig machen muss.
-
Statuscodes lesen. Ein Durchlauf, der beginnt,
403oder andere Herausforderungen zurückzugeben, signalisiert, dass die aktuelle Rate zu aggressiv ist. Das als Signal behandeln, zurückzuweichen, nicht als Rauschen, das man ignoriert.
Das umfassendere Playbook steht in how to scrape websites without getting blocked und dem tieferen Einblick in how to bypass captchas while web scraping. Da Clutch Teile seiner Seiten clientseitig rendert, erklärt unser Leitfaden zu scraping JavaScript pages with Python, warum Rendering wichtig ist. Wenn man den eigenen Traffic lieber durch einen rotierenden Pool leiten möchte statt die verwaltete API zu nutzen, bietet der Smart AI Proxy (auch AI Proxy genannt) dieselbe Residential-IP-Rotation als Drop-in-Proxy-Endpunkt.
Ist es legal, Clutch.co zu scrapen?
Ob das Scrapen von Clutch.co erlaubt ist, hängt von Clutchs Nutzungsbedingungen, der eigenen Rechtsordnung und der Verwendung der Daten ab. Clutchs Bedingungen schränken den automatisierten Zugriff ein, sodass Scraping gegen diese Bedingungen verstoßen kann, unabhängig davon, wie sorgfältig das Tooling ist. Keiner der Codes hier ändert das; er macht nur den technischen Teil funktionsfähig. Die Clutch-Nutzungsbedingungen und die robots.txt lesen und beide als Grenze für das Gesammelte betrachten. Clutch veröffentlicht keine öffentliche, offene API für sein Verzeichnis, sodass es keinen sanktionierten Endpunkt gibt, der der Seite vorzuziehen wäre; das macht die Einhaltung der angegebenen Grenzen wichtiger, nicht weniger.
Einige lohnenswerte Leitlinien. Nur öffentliche Unternehmens-Listing-Daten sammeln: Unternehmensname, Bewertung, Anzahl der Bewertungen, Mindestprojektgröße, Stundensatz, Standort und Profillink, die jeder auf einer Kategorieseite ohne Konto sehen kann. Das Anfragevolumen bescheiden halten, damit Clutchs Server nicht belastet werden, und den Durchlauf staffeln statt ein ganzes Verzeichnis auf einmal abzurufen. Wenn die Daten kommerziell wiederverwendet werden sollen, für Outreach, Weiterverkauf oder ein Produkt, eine Genehmigung oder offizielle Vereinbarung einholen statt davon auszugehen, dass Schweigen Zustimmung ist.
Dieser Leitfaden ist bewusst auf öffentliche Verzeichnis- und Kategorieseiten beschränkt, weil das die Linie ist, die die Arbeit vertretbar hält. Er behandelt nichts hinter einem Login, persönliche Daten von Bewertern, Kontaktdaten, die nicht öffentlich aufgeführt sind, oder urheberrechtlich geschützten Bewertungstext, den man als eigenen weiterverbreiten würde. Nur öffentliche Unternehmens-Listing-Daten. Wenn das Projekt mehr erfordert, ist eine Datenpartnerschaft mit Clutch der richtige Weg, kein cleverer Scraper.
Wichtigste Erkenntnisse
-
Clutch blockiert einfache Anfragen. Ein einfaches
requests.getgibt meist einen 403 zurück, also muss die Seite hinter einer vertrauenswürdigen IP gerendert werden, bevor man sie parsen kann. -
Den JS-Token über die Crawling API verwenden. Ein Aufruf rendert die Seite in einem echten Browser und rotiert Residential-IPs;
ajax_waitundpage_waitsteuern, wie lange auf Inhalte gewartet wird. -
BeautifulSoup übernimmt die Extraktion. Jeden
li.providerinul.providers__listauswählen, dann Unternehmensname, Bewertung, Rezensionen, Mindestprojektgröße, Stundensatz, Standort und Profil-URL lesen, und damit rechnen, dass die Selektoren sich verschieben. -
Mit dem page-Parameter paginieren. Clutch durchläuft Seiten via
?page=N, also durchläuft ein echter Job die Seiten, verwendet denselben Parser und schläft zwischen Anfragen. - Auf öffentlichen Daten bleiben. Clutchs ToS und robots.txt respektieren, Volumen bescheiden halten und vor jeder kommerziellen Wiederverwendung eine Genehmigung einholen.
Häufig gestellte Fragen
Warum gibt eine einfache Anfrage an Clutch.co einen 403 zurück?
Clutch betreibt aggressiven Bot-Schutz. Eine Datacenter-IP, die eine offensichtlich automatisierte Anfrage stellt, wird herausgefordert oder mit einem 403 blockiert, bevor Listing-Daten ankommen. Um echte Daten zu erhalten, braucht man eine Anfrage, die die Seite rendert und von einer IP kommt, die die Plattform als echten Besucher liest, was der JS-Token der Crawling API für einen übernimmt.
Brauche ich den normalen Token oder den JS-Token für Clutch.co?
Den JS-Token. Der normale Token ruft statisches HTML ab und führt keinen Browser aus, sodass er auf einer verteidigten, teilweise clientseitig gerenderten Seite wie Clutch dazu neigt, leer oder blockiert zurückzukommen. Der JS-Token rendert die Seite in einem echten Browser und leitet durch rotierende Residential-IPs, bevor er das HTML zurückgibt, sodass die Unternehmenskarten vorhanden sind, wenn BeautifulSoup sie parst.
Welche Daten kann ich von einem Clutch.co-Listing scrapen?
Von einer öffentlichen Kategorieseite kann man den Unternehmensnamen jedes Anbieters, die aggregierte Bewertung, die Anzahl der Rezensionen, die Mindestprojektgröße, die Stundensatzspanne, den Standort und den Link zu seinem vollständigen Profil lesen. Dieser Leitfaden zieht genau diese Felder. Alles hinter einem Login, persönliche Daten von Bewertern oder private Kontaktdaten sind außerhalb des Umfangs und außerhalb der Grenzen.
Wie scrape ich mehrere Seiten von Clutch.co-Ergebnissen?
Clutch paginiert mit einem page-Abfrageparameter, also wird jede URL als f"{base_url}?page={page}" aufgebaut und die Seitenzahlen in einer Schleife durchlaufen. Jede Seite über dieselbe Funktion abrufen, denselben Parser ausführen und die Zeilen sammeln. Ein kurzes time.sleep zwischen Anfragen hinzufügen, um die Seite nicht zu überfluten, und die Seitenanzahl erhöhen, wenn die Ausgabe korrekt aussieht.
Meine Selektoren geben für jede Karte "N/A" zurück. Was hat sich geändert?
Höchstwahrscheinlich Clutchs Markup. Klassenamen ändern sich ohne Vorankündigung, sodass Selektoren, die letzten Monat funktionierten, brechen können. Ein Live-Listing in den Entwicklerwerkzeugen des Browsers erneut inspizieren und die Selektoren aktualisieren, zum Beispiel h3.provider__title oder span.sg-rating__number. Periodische Selektor-Wartung ist für jeden Produktions-Scraper normal.
Wie vermeide ich das Blockieren beim Scrapen von Clutch.co?
Die Pro-IP-Anfragerate niedrig halten, den Durchlauf mit einem Schlaf zwischen Anfragen staffeln und durch rotierende Residential-IPs leiten, sodass keine einzelne Adresse ein Rate-Limit auslöst. Die Crawling API verwaltet Rotation und einen vertrauenswürdigen IP-Pool; wenn man einen eigenen Stack aufbaut, ist das der Teil, in den man investieren sollte. Die Statuscodes beobachten und zurückweichen, wenn man beginnt, 403-Antworten oder andere Herausforderungen zu sehen.
Crawlen Sie jede Website im großen Maßstab, ohne gegen die Infrastruktur zu kämpfen.
Crawlbase übernimmt Proxys, Fingerprints und CAPTCHAs, damit Ihr Team Datenpipelines ausliefert, statt Crawl-Infrastruktur zu pflegen. 1.000 Anfragen kostenlos, keine Karte erforderlich.
