# Clutch.co Scraper - Agency Ratings, Reviews & Contacts (`techforce.global/clutch-scraper`) Actor

Scrape verified agency and software company data from Clutch.co: ratings, pricing, reviews, and contact details across dev, design, marketing, SEO, mobile, and IT services categories.Deliver results straight to Notion, Slack, Airtable, or Sheets via MCP.

- **URL**: https://apify.com/techforce.global/clutch-scraper.md
- **Developed by:** [Techforce Global](https://apify.com/techforce.global) (community)
- **Categories:** Automation, Lead generation, Agents
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

### Clutch.co Company Scraper & MCP Connector

Pull **verified B2B service-provider data straight off Clutch.co** — agencies and dev shops across software development, web design, digital marketing, SEO, mobile app development, and IT services. **No login, no manual profile-by-profile copy-pasting, no CAPTCHA-solving by hand.**

Built for agencies doing competitor research, sales teams prospecting for outsourcing partners, and researchers who need Clutch's ratings, reviews, and contact data as clean, structured records — in minutes, not hours of clicking through listings.

> **Pick a category, name, or location → get every company's rating, pricing, reviews, and full contact/team profile → deliver it straight into Notion, Slack, Airtable, or your CRM.**

***

### ⭐ Why This Actor?

- ✅ **Three ways in** — browse a full category, search by company name, or filter by location; combine name + category for a fallback search-then-browse flow.
- ✅ **Deep profile enrichment** — optionally visit every company's profile page for overview, about/team, portfolio, offices, verification badges, and full contact details (website, phone, email, LinkedIn, Twitter, Facebook, Instagram).
- ✅ **Reviews on demand** — pull the first page of reviews by default, or toggle full pagination to capture every review left on a profile.
- ✅ **Concurrent enrichment** — profile pages are scraped concurrently (5 at a time by default) so enrichment doesn't run one company at a time.
- ✅ **Cloudflare-aware** — every scrape path detects "Just a moment" interstitials and waits them out, with retry-and-backoff on failed page loads.
- ✅ **Never returns messy nulls** — every missing field falls back to `"N/A"` instead of `null`, so the dataset stays clean and consistent.
- ✅ **Deliver anywhere via MCP connectors** — push scraped companies straight into Notion, Slack, Airtable, Google Sheets, and more.
- ✅ **Export-ready** — JSON, CSV, Excel, JSONL, or XML, or direct API integration for your own pipeline.

***

### 📝 Use Cases & ROI

| Use Case | Time Saved | What You Get |
| --- | --- | --- |
| **Outsourcing partner sourcing** | 3–6 hrs/search | Every agency in a category/location, ranked by rating and hourly rate, ready to shortlist |
| **Competitor benchmarking** | 2–4 hrs/report | Pricing, team size, reviews, and positioning for direct competitors |
| **Sales prospecting** | 3–5 hrs/list | Verified contact details (email, phone, website, socials) for cold outreach |
| **Reputation & review analysis** | 2–5 hrs/scan | Full review history per company for sentiment and win/loss patterns |
| **Market mapping** | 4–8 hrs/build | Structured data to power directories, comparison sites, or internal databases |

***

### 🚀 How to Use

1. Open the Actor on Apify.
2. Pick a **Category** from the dropdown (e.g. Software Developers, SEO Companies), or leave it blank to scrape all categories.
3. *(Optional)* Enter a **Filter by Name** to search for a specific company by name instead of browsing a category.
4. *(Optional)* Enter a **Location Filter** using Clutch's location slug (e.g. `new-york-city`, `india`, `united-kingdom`).
5. Set **Max Pages** and **Max Records** to control how much of the listing to pull.
6. Toggle **Scrape Profile Pages** to enrich each company with full profile data, and **Scrape All Reviews** to paginate through every review instead of just the first page.
7. *(Optional)* Pick an **MCP connector** to deliver scraped companies into Notion, Slack, Airtable, etc.
8. Click **Run** — results stream into the dataset as each company is scraped.
9. Download as JSON, CSV, Excel, JSONL, or XML — or let the connector push them into your tools automatically.

> 💡 First time with a connector? Run once with a connector selected — the run log prints the connector's available tool names, so you know what to put in **Connector tool name**.

***

### 🧩 Input Configuration

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `category` | Select | Optional | One of `software-developers`, `web-designers`, `digital-marketing`, `seo-companies`, `mobile-app-developers`, `it-services`. Leave blank to scrape all categories. |
| `filterName` | String | Optional | Case-insensitive substring filter. If set with no `category`/`location`, searches Clutch directly by name (falling back to a category scrape if the search returns nothing). |
| `location` | String | Optional | Clutch's URL-based location slug (e.g. `new-york-city`, `india`, `united-kingdom`). Leave blank to scrape globally. |
| `maxPages` | Integer | Optional | Max listing pages to paginate through. Default: `1`. |
| `maxRecords` | Integer | Optional | Max total companies to collect (`0` = unlimited). Default: `10`. |
| `scrapeProfiles` | Boolean | Optional | Visit each company's profile page for reviews, team, portfolio, and contact data. Slower but much richer. Default: `true`. |
| `scrapeAllReviews` | Boolean | Optional | Paginate through every review page per profile instead of just the first ~10. Default: `false`. |
| `mcpConnector` | Connector | Optional | Deliver scraped companies into a connector you've authorized (Notion, Slack, Airtable, Google Sheets, …). |
| `deliveryMode` | Enum | Optional | `summary` (one call with the full company list), `chunked` (split a large list across multiple calls), `perCompany` (one call per company), or `none`. Default: `summary`. |
| `mcpTool` | String | Optional | Tool to call on the connector (e.g. `create_page`, `send_message`, `append_row`). |
| `mcpArguments` | Object | Optional | Arguments for the tool; string values support `{placeholders}`. |
| `mcpMessageTemplate` | String | Optional | Template rendered per delivery, exposed as the `{message}` placeholder. |

> \[!TIP]
> Combine `category` with `location` to shortlist agencies in a specific market. Use `filterName` on its own to look up one company by name.

#### Example — Scrape a category with full profile enrichment

```json
{
  "category": "software-developers",
  "location": "india",
  "maxPages": 3,
  "maxRecords": 50,
  "scrapeProfiles": true,
  "scrapeAllReviews": false
}
```

#### Example — Look up one company by name and post it to Slack

```json
{
  "filterName": "Techforce Global",
  "scrapeProfiles": true,
  "mcpConnector": "<your-slack-connector>",
  "deliveryMode": "perCompany",
  "mcpTool": "send_message",
  "mcpArguments": { "channel": "#agency-leads", "text": "{message}" },
  "mcpMessageTemplate": "{name} — {rating} — {location} — {website} — {profileLink}"
}
```

#### Example — Scrape and log a summary into Notion

```json
{
  "category": "seo-companies",
  "maxPages": 2,
  "maxRecords": 30,
  "mcpConnector": "<your-notion-connector>",
  "deliveryMode": "chunked",
  "mcpTool": "create_page",
  "mcpArguments": {
    "parent": { "page_id": "<your-page-id>" },
    "pages": [
      {
        "properties": { "title": "Clutch companies — part {part}/{partCount}" },
        "content": "{companies}"
      }
    ]
  }
}
```

#### Placeholders available in arguments / template

**Summary & chunked modes:** `{companyCount}` · `{companies}` · `{message}`
**Chunked mode adds:** `{part}` · `{partCount}`
**Per-company mode:** any field from that company's output record — `{name}` · `{profileLink}` · `{rating}` · `{location}` · `{hourlyRate}` · `{minProjectSize}` · `{description}` · `{website}` · `{contactEmail}` · `{contactPhone}` · `{contactLinkedin}` · `{contactWebsite}` — plus `{companyText}` (a formatted block) and `{message}`

***

### 📦 Output Fields

| Field | Description |
| --- | --- |
| `name` | Company name |
| `profileLink` | Direct link to the company's Clutch profile |
| `rating` | Clutch rating (e.g. `4.9`) |
| `location` | Primary location as shown on the listing |
| `hourlyRate` | Listed hourly rate band |
| `minProjectSize` | Minimum project size |
| `description` | Short listing description |
| `website` | Company website (from the listing/profile header) |
| `overviewName` / `overviewPosition` / `overviewAvatar` | Contact shown in the profile's overview block *(profile scrape only)* |
| `employees` / `yearFounded` / `languages` / `timezones` / `reviewCount` | Highlights from the profile header *(profile scrape only)* |
| `languagesList` | Full list of languages spoken *(profile scrape only)* |
| `offices` | Array of office objects: `address`, `phone`, `employees`, `verified` *(profile scrape only)* |
| `contactWebsite` / `contactLinkedin` / `contactTwitter` / `contactFacebook` / `contactInstagram` / `contactPhone` / `contactEmail` | Contact details from the profile's contact section *(profile scrape only)* |
| `teamBio` / `quickFacts` / `teamBreakdown` / `tools` | About/team section content *(profile scrape only)* |
| `members` | Array of team member objects: `name`, `position`, `bio`, `photo` *(profile scrape only)* |
| `reviews` | Array of scraped reviews (first page, or all pages if `scrapeAllReviews` is enabled) *(profile scrape only)* |

Fields marked *(profile scrape only)* are only populated when `scrapeProfiles` is enabled; otherwise the output contains just the listing-level fields (`name` through `website`). Any field Clutch doesn't expose for a given company returns `"N/A"` rather than being omitted.

#### Example Output

```json
{
  "name": "Techforce Global",
  "profileLink": "https://clutch.co/profile/techforce-global",
  "rating": "4.9",
  "location": "Ahmedabad, India",
  "hourlyRate": "$25 - $49 / hr",
  "minProjectSize": "$1,000+",
  "description": "Techforce Global is a web & mobile app development company...",
  "website": "https://www.techforceglobal.com",
  "employees": "50 - 249",
  "yearFounded": "2015",
  "reviewCount": "12",
  "contactWebsite": "https://www.techforceglobal.com",
  "contactEmail": "N/A",
  "contactPhone": "+91 XXXXXXXXXX",
  "offices": [
    { "address": ["Ahmedabad", "Gujarat", "India"], "phone": "N/A", "employees": "N/A", "verified": true }
  ]
}
```

> You can download the dataset in various formats such as JSON, HTML, CSV, Excel, or XML.

***

### 🗺️ Supported Categories

| Category value | Description | Clutch URL |
| --- | --- | --- |
| `software-developers` | Software Developers | clutch.co/developers |
| `web-designers` | Web Designers | clutch.co/web-designers |
| `digital-marketing` | Digital Marketing | clutch.co/agencies/digital-marketing |
| `seo-companies` | SEO Companies | clutch.co/seo-firms |
| `mobile-app-developers` | Mobile App Developers | clutch.co/app-developers |
| `it-services` | IT Services | clutch.co/it-services |

Leave `category` blank to scrape across all six.

***

### 🔌 Integrations & Delivery

Deliver scraped companies into any MCP connector you've authorized in Apify — no glue code, no webhooks:

- **Notion** — log a running page of companies (use `chunked` mode for large lists so Notion never times out)
- **Slack / Discord** — post companies or summaries to a channel as they're found
- **Airtable / Google Sheets** — append a structured row per company
- **Jira / Linear / GitHub** — open a follow-up task per company (e.g. outreach or vendor review)
- …or any other MCP-compatible connector

Credentials stay private — delivery runs through the **Apify MCP Proxy**, so the Actor never sees your connector tokens. You can also consume the dataset directly via the **Apify API**, or wire it into **n8n, Zapier, and Make**.

> ⚙️ **Delivery modes:** `summary` sends the full company list in one call, `chunked` splits a large list across a few calls/pages, and `perCompany` sends one call per scraped company. MCP delivery only runs on the Apify platform and never affects what's saved to the dataset.

#### 🔧 Connector Tool Arguments Reference

Ready-to-paste `mcpTool` + `mcpArguments` combos for common connectors.

**Slack** — `mcpTool: "send_message"`, mode `perCompany` or `summary`

```json
{ "channel": "#agency-leads", "text": "{message}" }
```

**Discord** — `mcpTool: "send_message"`, mode `perCompany` or `summary`

```json
{ "channel_id": "<your-channel-id>", "content": "{message}" }
```

**Notion** — `mcpTool: "create_page"`, mode `perCompany` (one page per company)

```json
{
  "parent": { "database_id": "<your-database-id>" },
  "properties": {
    "Name": { "title": [{ "text": { "content": "{name}" } }] },
    "Rating": { "rich_text": [{ "text": { "content": "{rating}" } }] },
    "Location": { "rich_text": [{ "text": { "content": "{location}" } }] },
    "Hourly Rate": { "rich_text": [{ "text": { "content": "{hourlyRate}" } }] },
    "Website": { "url": "{website}" },
    "Profile": { "url": "{profileLink}" }
  }
}
```

**Notion** — `mcpTool: "create_page"`, mode `chunked` (one page per batch of companies)

```json
{
  "parent": { "page_id": "<your-page-id>" },
  "properties": { "title": [{ "text": { "content": "Clutch companies — part {part}/{partCount}" } }] },
  "children": [
    { "object": "block", "type": "paragraph", "paragraph": { "rich_text": [{ "text": { "content": "{companies}" } }] } }
  ]
}
```

**Airtable** — `mcpTool: "create_record"`, mode `perCompany`

```json
{
  "table": "Clutch Companies",
  "fields": {
    "Name": "{name}",
    "Rating": "{rating}",
    "Location": "{location}",
    "Hourly Rate": "{hourlyRate}",
    "Website": "{website}",
    "Email": "{contactEmail}",
    "Phone": "{contactPhone}",
    "Profile": "{profileLink}"
  }
}
```

**Google Sheets** — `mcpTool: "append_row"`, mode `perCompany`

```json
{
  "spreadsheetId": "<your-spreadsheet-id>",
  "range": "Sheet1!A:G",
  "values": [
    ["{name}", "{rating}", "{location}", "{hourlyRate}", "{website}", "{contactEmail}", "{profileLink}"]
  ]
}
```

**Jira** — `mcpTool: "create_issue"`, mode `perCompany`

```json
{
  "project": "BIZ",
  "issueType": "Task",
  "summary": "Vendor review: {name} ({location})",
  "description": "{message}"
}
```

**Linear** — `mcpTool: "create_issue"`, mode `perCompany`

```json
{
  "teamId": "<your-team-id>",
  "title": "Vendor review: {name} ({location})",
  "description": "{message}"
}
```

**GitHub** — `mcpTool: "create_issue"`, mode `perCompany`

```json
{
  "owner": "your-org",
  "repo": "vendor-tracking",
  "title": "{name} — {location}",
  "body": "{message}"
}
```

For the Jira / Linear / GitHub examples above, pair with this `mcpMessageTemplate`:

```
{name} — {rating} — {location} — {hourlyRate}
{website}
{profileLink}
```

***

### 🛠️ How It Works

`my_actor/main.py` reads the input and picks a scraping strategy:

1. **If `filterName` is set with no `category`/`location`**, it searches Clutch directly (`scraper.scrape_by_name`) and automatically falls back to scraping every category with the name filter applied if the search returns zero results.
2. **Otherwise**, it scrapes one category (or all six if `category` is blank) via `scraper.scrape_all`, paginating up to `maxPages`, applying `location`/`filterName` filters, and stopping once `maxRecords` is reached.
3. **If `scrapeProfiles` is enabled**, each company's profile page is visited concurrently (`profileScraper.scrape_profile`, 5 at a time by default) to pull overview, about/team, portfolio, offices, verification, contact details, and reviews — paginating every review page if `scrapeAllReviews` is on.
4. Every scrape path runs a stealth Playwright context (spoofed `navigator.webdriver`, custom user agent/locale/timezone), detects Cloudflare "Just a moment" interstitials and waits them out, and retries failed page loads with backoff.
5. Results are pushed to the dataset as they're collected, then — if a connector is configured — delivered via MCP once scraping finishes.

**Built with:** [Apify SDK for Python](https://docs.apify.com/sdk/python/) · [Playwright](https://playwright.dev/python/) · [MCP](https://modelcontextprotocol.io/)

***

### 🛠 Running Locally

```bash
## Install dependencies
pip install -r requirements.txt
playwright install chromium --with-deps

## Create local input file
mkdir -p storage/key_value_stores/default
echo '{
  "category": "software-developers",
  "location": "india",
  "maxPages": 1,
  "maxRecords": 10,
  "scrapeProfiles": true,
  "scrapeAllReviews": false
}' > storage/key_value_stores/default/INPUT.json

## Run the actor
python -m my_actor
```

***

### 🆘 Support

For issues, custom scraping requests, or feature suggestions:
**Email**: bhavin.shah@techforceglobal.com

***

#### Need a Custom Pipeline?

Want multi-category batch runs, scheduled refreshes, deeper enrichment, or a full data-warehouse integration?

#### [📅 Book a Free 15-min Consultation](https://calendly.com/techforce-global/intro-meeting)

***

Made with ❤️ by **[Techforce](https://www.techforceglobal.com)**
Specialists in High-Performance Web Scrapers and AI Automation.

***

### Disclaimer

This Actor is an independent tool and is not affiliated with, endorsed by, or sponsored by Clutch.co. Clutch® is a trademark of its respective owner; all trademarks are property of their respective owners. The Actor collects only publicly available information (company listings, ratings, and profile data shown on public pages) and does not log into, or scrape behind the authentication of, any platform. Use the data responsibly and in compliance with applicable laws (including GDPR/CCPA) and Clutch's terms of service.

# Actor input Schema

## `category` (type: `string`):

Select a Clutch category to scrape. Leave blank to scrape all categories.

## `filterName` (type: `string`):

Case-insensitive substring filter. Only companies whose name contains this string will be included in the output.

## `location` (type: `string`):

Filter companies by location. Uses Clutch's URL-based location slug (e.g. 'new-york-city', 'india', 'united-kingdom'). Leave blank to scrape globally.

## `maxPages` (type: `integer`):

Maximum number of listing pages to paginate through

## `maxRecords` (type: `integer`):

Maximum total companies to collect (0 = unlimited)

## `scrapeProfiles` (type: `boolean`):

Visit each company's full profile page to collect detailed data (reviews, team, portfolio, contact, etc.). Slower but much richer data.

## `scrapeAllReviews` (type: `boolean`):

Paginate through all review pages for each profile. When disabled, only the first page (~10 reviews) is collected. Enabling this is slower but collects every review.

## `mcpConnector` (type: `string`):

Optionally deliver scraped companies into a connector you have authorized — Notion, Slack, Airtable, Google Sheets, or any MCP-compatible connector. Leave empty to only save the result to the dataset.

## `deliveryMode` (type: `string`):

How to deliver to the connector: 'summary' (one call with all scraped companies), 'chunked' (split a long company list across a few calls so services like Notion never time out), 'perCompany' (one call per company), or 'none' (save to dataset only).

## `mcpTool` (type: `string`):

Name of the tool to call on the connector (e.g. 'create\_page' for Notion, 'send\_message' for Slack, 'append\_row' for Google Sheets). If unsure, run once with a connector selected — the log lists the connector's available tools.

## `mcpArguments` (type: `object`):

Arguments passed to the connector tool. String values support {placeholders}. In 'summary' mode: {companyCount}, {companies} (all companies as text) and {message} (the rendered template below). In 'chunked' mode: same as summary but {companies} holds one part of the list and {part}/{partCount} give the 1-based part number and total. In 'perCompany' mode: any field from that company's output record (e.g. {name}, {profileLink}, {rating}, {location}, {hourlyRate}, {website}), plus {companyText} (a formatted block) and {message}. Example for Slack: {"channel": "#leads", "text": "{message}"}.

## `mcpMessageTemplate` (type: `string`):

Optional template rendered and exposed as the {message} placeholder in the tool arguments. Summary example: 'Scraped {companyCount} companies from Clutch:\n\n{companies}'. Per-company example: '{name} — {rating} — {profileLink}'.

## Actor input object example

```json
{
  "category": "software-developers",
  "maxPages": 1,
  "maxRecords": 10,
  "scrapeProfiles": true,
  "scrapeAllReviews": false,
  "deliveryMode": "summary",
  "mcpTool": "",
  "mcpArguments": {},
  "mcpMessageTemplate": ""
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("techforce.global/clutch-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("techforce.global/clutch-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call techforce.global/clutch-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,techforce.global/clutch-scraper"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/M19Wyg71hv258QhpN/builds/49veEoCjLVxymeC6I/openapi.json
