# GoodFirms Scraper: IT Companies, Agencies & Reviews (`scrapewise/goodfirms-scraper`) Actor

Scrape GoodFirms directories and company profiles without login: name, website, location, hourly rate, team size, founded, rating, review count, services with focus %, industries, offices and client reviews. Filters by rate, size and reviews. Error rows are free.

- **URL**: https://apify.com/scrapewise/goodfirms-scraper.md
- **Developed by:** [Scrapewise Data](https://apify.com/scrapewise) (community)
- **Categories:** Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.75 / 1,000 company or review delivereds

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

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## GoodFirms Scraper: IT companies, agencies, services and client reviews

Scrape [GoodFirms](https://www.goodfirms.co) **without an account, cookies or a browser**: every
company on any GoodFirms directory (software development, app development, digital marketing, web
design, by country or city) with name, website, location and address, hourly rate, team size,
year founded, rating, review count, short description and the top review quote. Turn on profile
details to add services and industries with their focus percentage, client size focus, every
office, sub-ratings, GoodFirms' AI review summary, notable clients, portfolio count,
certifications and social links. Turn on reviews to get one row per client review.

Built for B2B lead lists, vendor and outsourcing research, agency market maps, competitor
benchmarking and review datasets for sentiment analysis and LLMs.

### At a glance

- **Price per 1,000 companies, Free plan:** US$ 2.50
- **Fee per run start:** None
- **Filters:** Hourly rate, team size, minimum reviews, sort
- **Services and industries with focus %:** Yes
- **Every office address, AI review summary, notable clients:** Yes
- **Error rows (bad link, profile not found):** Free, with an `errorCode`

### One real row

From a test run on 2026-09-28 (software development directory, first company):

```json
{
  "type": "company",
  "companyName": "Instinctools",
  "goodfirmsId": 579,
  "profileUrl": "https://www.goodfirms.co/company/instinctools",
  "website": "https://www.instinctools.com/",
  "logoUrl": "https://assets.goodfirms.co/services/medium/instinctools.png?v=1790574638",
  "rating": 4.9,
  "reviewCount": 27,
  "hourlyRate": "$25 - $49/hr",
  "employees": "250 - 999",
  "founded": 2000,
  "location": "Potomac, United States",
  "country": "United States",
  "address": {"street": "12430 Park Potomac Ave", "city": "Potomac", "region": "Maryland", "postalCode": "20854", "country": "US"},
  "shortDescription": "*instinctools is a leading software product development company that provides tailor-made IT and digital transformation solutions for businesses of all sizes…",
  "whyChooseUs": ["Trusted engineering partner for AI-driven growth", "Technology solutions built for scalable growth", "Transparent and flexible engagement approach"],
  "topReview": {"text": "The team delivers on time and within budget, proactively asking how to help the client and providing new ideas.", "reviewerTitle": "Head of Engineering"},
  "sourceUrl": "https://www.goodfirms.co/directory/languages/top-software-development-companies",
  "page": 1,
  "position": 1,
  "scrapedAt": "2026-09-28T11:30:27Z",
  "errorCode": null,
  "error": null
}
```

With `includeProfileDetails` the same row also carries `tagline`, `headquarters`, `offices` (4
addresses in the US, Germany, Poland and Canada), `about`, `services` (14, such as
`{"name": "Mobile App Development", "percent": 10}`), `industries` (9), `clientFocus`
(`{"Small Business": 35, "Medium Business": 45, "Large Business": 20}`), `ratingQuality` 4.9,
`ratingSchedule` 4.8, `ratingCommunication` 4.9, `reviewSummary`, `notableClients` (14),
`portfolioCount` 68, `certifications` (ISO 27001, ISO 9001:2015), `socialLinks` and `areaServed`.

A review row (`type: "review"`): `reviewDate` "2026-06-03", `rating` 5.0 with quality,
communication and schedule sub-ratings, `title`, `text`, `services` \["Mobile App Development",
"Software Development"], `reviewerTitle` "Founder", `reviewerCompany` "Hiya Healthcare",
`verified` true.

### Input

| Field | Type | What it does |
|---|---|---|
| `startUrls` (also `searchUrl`, `urls`) | list | GoodFirms directory pages, company profiles (`goodfirms.co/company/<name>`) or company slugs. Filters already in a link are kept. |
| `maxCompaniesPerUrl` (also `maxItems`) | integer, default 48 | Companies per directory link. GoodFirms shows 48 per page. `0` = the whole list. |
| `sortBy` | `goodfirms`, `mostReviews`, `highestRated` | The directory's own orders. |
| `hourlyRate` | list | `<25`, `25-49`, `50-99`, `100-149`, `150-199`, `200-300`, `300+`, `NA`. |
| `employees` | list | `2-9`, `10-49`, `50-249`, `250-999`, `1000-9999`, `10000+`. |
| `minReviews` | integer | 1, 3, 5, 10, 15 or 20 (other numbers round down). |
| `includeProfileDetails` | boolean, default false | Opens each profile and adds the fields listed above. Same price per company. |
| `includeReviews` | boolean, default false | One row per client review, newest first. Turns on profile details. |
| `maxReviewsPerCompany` | integer, default 10 | Reviews per company. `0` = every review. |
| `proxyConfiguration` | proxy | Apify datacenter proxy by default. |

### Price

**US$ 2.50 per 1,000 rows** on the Free plan (a company or a review), no start fee. Rows with an
`errorCode` are free; a company is never charged twice in a run, even when it appears in two of
your directories.

### Errors you may see

| `errorCode` | Meaning | Charged |
|---|---|---|
| `INVALID_URL` | not a goodfirms.co link or company slug | no |
| `NO_COMPANIES` | the page has no company list (software product pages, for example) | no |
| `NOT_FOUND` | no company profile at that address | no |
| `ONLY_FREELANCERS` | every company on the list is an individual freelancer profile | no |
| `FREELANCER_SKIPPED` | the profile you asked for belongs to an individual freelancer | no |
| `BLOCKED` | GoodFirms did not answer after five attempts on new IPs; run again | no |
| `NOT_REACHED` | the run timeout arrived before this link | no |
| `INVALID_INPUT` | a filter value is not valid | no |
| `ITEM_UNREADABLE`, `UNEXPECTED` | a card came in a shape we did not expect; the rest of the run goes on | no |

### Good to know

- **Whole directories, not a sample.** The Actor follows GoodFirms' own pages to the end (the
  software development list has over 500 pages of 48 companies).
- **Individual freelancer profiles are skipped.** GoodFirms lists some one-person profiles under
  the team size "Freelancer"; those are personal data and are not collected or charged.
- **No personal data from reviews.** A review row carries the reviewer's role and company as shown
  on GoodFirms, never the reviewer's name, initial or photo. Company phone numbers and e-mails
  are not collected either.
- **Website links are clean**: GoodFirms' tracking parameters (`utm_*`) are removed.
- Something broke? Open an issue on the Actor page.

### FAQ

**Do I need a GoodFirms account?** No. Nothing to log in to, no cookies to paste.

**Which links work?** Any GoodFirms page that lists service companies: the main categories, country
and city lists, and service pages such as `goodfirms.co/content-marketing`. Copy the link from
your browser after choosing filters on GoodFirms, or use the filter fields here.

**How fast is it?** A directory page of 48 companies takes about two seconds. With profile
details, five profiles are read in parallel (300 profiles took about one minute in a test).

**Can I use it from n8n, Make, Zapier or an AI agent?** Yes, through the Apify app or the Apify
MCP server. Error rows are free, so an agent can explore cheaply.

**What if a run is cut by its timeout?** The Actor stops 45 seconds before the limit and ends
successfully with what it delivered, telling you in the status message how to get the rest.

### Changelog

- **0.1 (2026-09-28)**: first version. Directory and profile links, hourly rate, team size and
  review filters, profile details, client reviews without reviewer names, free error rows.

# Actor input Schema

## `startUrls` (type: `array`):

One per line: any GoodFirms directory page (for example goodfirms.co/directory/languages/top-software-development-companies, a country or city list, or goodfirms.co/content-marketing), a company profile (goodfirms.co/company/<name>) or just the company slug. Filters already in a directory link are kept. Also accepts 'searchUrl' and 'urls'.

## `maxCompaniesPerUrl` (type: `integer`):

Stop each directory after this many companies. GoodFirms shows 48 per page. 0 = every page of the list. Also accepts 'maxItems'.

## `sortBy` (type: `string`):

Order of the directory, as on GoodFirms. With a company limit it also decides which companies you get.

## `hourlyRate` (type: `array`):

Keep only companies in these hourly rate bands. Empty = all. Values: <25, 25-49, 50-99, 100-149, 150-199, 200-300, 300+, NA.

## `employees` (type: `array`):

Keep only companies with these team sizes. Empty = all. Values: 2-9, 10-49, 50-249, 250-999, 1000-9999, 10000+.

## `minReviews` (type: `integer`):

Keep only companies with at least this many reviews. GoodFirms steps: 1, 3, 5, 10, 15, 20 (other numbers round down).

## `includeProfileDetails` (type: `boolean`):

Open each company profile and add services and industries with focus %, client size focus, every office address, about text, sub-ratings (quality, schedule, communication), GoodFirms' AI review summary, notable clients, portfolio count, certifications and social links. Same price per company; the run takes longer.

## `includeReviews` (type: `boolean`):

Add one row per client review (date, title, text, overall and sub-ratings, services, reviewer role and company). Reviewer names are never collected. Each review is charged as one row. Turns on profile details.

## `maxReviewsPerCompany` (type: `integer`):

Reviews per company when 'Include client reviews' is on, newest first. 0 = every review (15 per profile page).

## `proxyConfiguration` (type: `object`):

The default Apify Proxy (datacenter) works; tested with 30 directory pages and 6 profiles in a row without a block.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.goodfirms.co/directory/languages/top-software-development-companies"
  ],
  "maxCompaniesPerUrl": 48,
  "sortBy": "goodfirms",
  "includeProfileDetails": false,
  "includeReviews": false,
  "maxReviewsPerCompany": 10,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

No description

## `resultsCsv` (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 = {
    "startUrls": [
        "https://www.goodfirms.co/directory/languages/top-software-development-companies"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapewise/goodfirms-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 = { "startUrls": ["https://www.goodfirms.co/directory/languages/top-software-development-companies"] }

# Run the Actor and wait for it to finish
run = client.actor("scrapewise/goodfirms-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 '{
  "startUrls": [
    "https://www.goodfirms.co/directory/languages/top-software-development-companies"
  ]
}' |
apify call scrapewise/goodfirms-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scrapewise/goodfirms-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/UvhXNyGqgfuO7eaG9/builds/8pO5o3MhL18K7CQON/openapi.json
