# G2 Reviews & Products Scraper | AI, Competitor Intel (2026) (`factden/g2-reviews-scraper`) Actor

Scrape G2 reviews and products in real-time. 32 fields: 6 sub-ratings, switching competitors, structured pros/cons, LLM-ready markdown. Top 10 competitors ranked per product. Built for market research, competitive intelligence, sales enablement. No login, no proxy, no anti-bot. $4 per 1,000 rows.

- **URL**: https://apify.com/factden/g2-reviews-scraper.md
- **Developed by:** [FactDen](https://apify.com/factden) (community)
- **Categories:** Lead generation, AI, Automation
- **Stats:** 5 total users, 2 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: 4.00 out of 5 stars

## Pricing

from $4.00 / 1,000 dataset rows

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

## G2 Reviews & Products Scraper | AI, Competitor Intel (2026)

**G2 Reviews & Products Scraper** is an Apify actor that extracts public G2 reviews and product data in real time — with ranked top-10 competitors per product and an LLM-ready markdown field for direct RAG ingestion.

> **Real-time** G2 reviews (fresh page fetch on every run, no caching) — no login, no proxy setup, no anti-bot tuning, no CAPTCHA work. Apify proxy + DataDome / Cloudflare bypass run inside the actor.

> **$4 / 1,000 rows.** $0.01 per run. Uniform pricing across both modes (Reviews mode = $0.004 per review row, Products mode = $0.004 per discovered product). **Free tier**: new Apify users get **~1,250 rows free** with the $5 platform credit.

**Contents**: [What's different](#whats-different-about-this-g2-scraper) · [G2 API vs this scraper](#g2s-official-api-vs-this-scraper) · [Use cases](#common-use-cases-for-scraping-g2-reviews) · [Pricing](#pricing---how-much-does-it-cost-to-scrape-g2-reviews) · [FAQ](#faq)

### What's different about this G2 scraper

Two angles vs. every other G2 scraper on Apify Store:

🏆 **Top-10 competitors ranked per product** — mined from each reviewer's switching-from data and resolved to real product names (no opaque IDs). Battlecard data, no aggregation code needed.

🤖 **LLM-ready `markdownContent` per review** — self-contained markdown block, ready for direct vector-DB ingestion / RAG pipelines / LLM prompt context with zero formatting work.

> **Quick start (30 seconds):**
> 1. Click **Try for free** above; the input is pre-filled with 2 examples (a full G2 URL and a bare slug) so you can see both accepted formats at a glance.
> 2. Click **Start**. The run takes ~15 seconds and fits inside Apify's $5 free credit.
> 3. Download results as JSON, CSV, or Excel from the **Output** tab.

**No-setup checklist** — what every other G2 scraper makes you build yourself:

- **No login** or G2 account required (public review data only)
- **No proxy** configuration (Apify proxy network bundled)
- **No anti-bot** tuning (DataDome + Cloudflare bypass internal)
- **No CAPTCHA** handling (managed by the proxy stack)
- **No code** required for the simple flow (form-based input)
- **No subscription** (pay-per-event: per-run + per-row only)

### What does G2 Reviews Scraper do?

Two modes:

- **Reviews mode**: Enter G2 product URLs or bare slugs and get every public review back as a clean, structured row. 
  **32 fields per review** including 6 sub-ratings, structured pros / cons / problemsSolved / recommendations, switching history with named competitors, reviewer industry / role / company size / country, and an LLM-ready `markdownContent` field for direct RAG ingest.
- **Products mode**: Enter a keyword (e.g. `communication`, `CRM`, `project management`, `saas`) and get the top N matching products 
  with metadata. Useful for competitor discovery before pulling reviews.

<table>
  <tr>
    <td><img src="https://raw.githubusercontent.com/factden/apify-actor-assets/main/g2-reviews-scraper/01-input-form-reviews-mode.png?v=2" width="480" alt="G2 reviews scraper input form on Apify Console showing Reviews mode with Slack and Microsoft Teams URLs prefilled for 1-click trial"></td>
    <td><img src="https://raw.githubusercontent.com/factden/apify-actor-assets/main/g2-reviews-scraper/06-input-form-products-mode.png?v=2" width="480" alt="G2 reviews scraper Products mode input form on Apify Console with search query prefilled to communication and max products set to 100"></td>
  </tr>
  <tr>
    <td align="center"><sub>Reviews mode - extract every review</sub></td>
    <td align="center"><sub>Products mode - discover competitors</sub></td>
  </tr>
</table>

Works on **every G2 product page** — Slack, Salesforce, HubSpot, Zoom, Notion, Microsoft Teams, Asana, Figma, monday.com, Intercom, and any other G2 listing you paste.

Output renders in the run's **Output tab** with a dataset dropdown (Reviews / Products). Download as JSON, CSV, or Excel.

<p align="center"><img src="https://raw.githubusercontent.com/factden/apify-actor-assets/main/g2-reviews-scraper/02-output-tab-reviews-overview.png?v=2" width="1300" alt="Apify Output tab for G2 reviews scraper with Reviews and Products dataset dropdown and 100 percent column population on Pros, Cons, Switched-from-competitor, Previous Competitors"></p>

**Per-product `topCompetitors` view** — top 10 named competitors ranked by reviewer-mention count, populated automatically for every product:

<p align="center"><img src="https://raw.githubusercontent.com/factden/apify-actor-assets/main/g2-reviews-scraper/04-products-top-competitors.png?v=2" width="1300" alt="G2 products summary dataset showing topCompetitors field with 10 named competitors per product including Microsoft Teams, Google Workspace, Discord, Zoom Workplace for Slack and Microsoft Teams"></p>

### G2's Official API vs this scraper

Why this actor exists: G2's review data is publicly displayed on their product pages, but G2's official API is enterprise-tier (sales call, MSA, multi-month procurement). This actor gives you the same review data with a 30-second setup.

| | G2 Official API | This actor |
|---|---|---|
| Access | Enterprise contract | Apify account (free signup) |
| Setup time | Weeks (procurement + integration) | 30 seconds |
| Pricing model | Custom contract | $0.01 per run + $0.004 per row |
| Free trial | None published | ~1,250 rows free on Apify's $5 credit |
| Top-10 competitors ranked per product | — | ✅ `topCompetitors` |
| Named switching-from data (resolved to product names, not opaque IDs) | — | ✅ `previousCompetitors` + `whySwitched` |
| LLM-ready markdown per review | — | ✅ `markdownContent` |
| Schedule / webhook delivery | Bring your own | Native via Apify Schedules + Webhooks |

### Who G2 Reviews Scraper is for

- **Competitive intel analysts** mining switching-from signals and ranked top competitors per product.
- **Product marketers** building battlecards from structured pros / cons / switching-reason fields.
- **AI / RAG engineers** ingesting G2 review data into vector databases - `markdownContent` is chunk-ready.
- **Win-loss researchers** scoping returned reviews to their ICP using `reviewerIndustry`, `companySize`, `reviewerCountry`, and `reviewerRole` (when present) — post-download filtering on the dataset.
- **Sales enablement** mining detractor language with `minRating=1, maxRating=2` and the lowest-rated sort order.

### Common use cases for scraping G2 reviews

#### 1. Build a battlecard from competitor reviews

Pull reviews for your product + top 3 competitors. The per-product `topCompetitors` field surfaces who customers actually switch from. Structured `pros` / `cons` / `recommendations` drop directly into Notion / Slides.

```json
{
  "startUrls": ["slack", "microsoft-teams", "zoom-workplace", "rocket-chat"],
  "maxReviewsPerProduct": 500,
  "sortReviews": "helpful"
}
````

#### 2. Mine objection language for sales enablement

Pull the lowest-rated reviews of your product to find what detractors actually say. `cons` and `whySwitched` are objection-handling gold.

```json
{
  "startUrls": ["slack"],
  "minRating": 1,
  "maxRating": 2,
  "sortReviews": "rating_low"
}
```

#### 3. Feed G2 reviews into a RAG / AI agent pipeline

Each review's `markdownContent` is a self-contained markdown chunk ready for vector-DB ingestion. Attach metadata (`productSlug`, `overallRating`, `previousCompetitors`) for filtered retrieval.

```json
{
  "startUrls": ["slack", "microsoft-teams"],
  "maxReviewsPerProduct": 1000
}
```

#### 4. Monitor competitor G2 reviews with scheduled runs

Run daily with `fromDate` set to yesterday for incremental pulls. Wire an Apify webhook to push new reviews into Slack, Snowflake, BigQuery, or your CRM.

```json
{
  "startUrls": ["microsoft-teams"],
  "fromDate": "2026-05-22",
  "sortReviews": "newest"
}
```

### How to scrape G2 reviews - step-by-step

1. Click **Try for free** on the Apify Store page.
2. Pick a **mode** in the input form (Reviews or Products).
3. Reviews mode: paste G2 product URLs or bare slugs (one per line, up to 100). Products mode: enter a keyword in **Search query**.
4. (Optional) Set filters: max reviews per product, date range, rating range, sort order, verified-reviewers-only.
5. Click **Start**. Results appear in the Output tab as soon as the first product completes.

Measured throughput on a single product: **~60 reviews/sec** sustained (plus ~5s container start).

| Reviews / product | Run time | Cost |
|---|---|---|
| 100 | ~10s | $0.41 |
| 1,000 | ~25s | $4.01 |
| 10,000 | ~3 min | $40.01 |
| 39,000 (Slack) | ~12 min | $156.01 |

**Products run sequentially** for predictable memory and cost.

### Input

| Field | Type | Default | What it does |
|---|---|---|---|
| **Mode** | enum | `reviews` | `reviews` extracts reviews for the products in `startUrls`. `products` finds top products by keyword. |
| **G2 product URLs or slugs** | array | (prefilled with 2 examples: 1 URL + 1 slug) | Reviews mode only. Full G2 URLs or bare slugs, one per line. Up to 100 products per run. Renamed G2 slugs auto-resolve to the canonical G2 slug (the `slug` field on the products summary row records the slug we actually extracted under). |
| **Search query** | string | `communication` (prefilled) | Products mode only. Keyword for product lookup. Silently ignored in Reviews mode. |
| **Max products** | int | 25 | Products mode only. Up to 1000. |
| **Max reviews per product** | int | 100 | Hard ceiling per product. Default 100 keeps first-click runs under the $5 free credit (100 reviews ≈ $0.41). Raise it for the real pull. |
| **From date** | date | (none) | Only reviews submitted on or after this date. |
| **To date** | date | (none) | Only reviews submitted on or before this date. |
| **Min rating / Max rating** | 1-5 | 1 / 5 | Filter reviews by overall star rating. |
| **Sort reviews by** | enum | `newest` | `newest` / `helpful` / `rating_high` / `rating_low`. `rating_low` is the fastest path to negative-review pain-point mining. |
| **Verified reviewers only** | bool | false | When true, drops vendor-submitted rows; keeps reviews from verified G2 reviewers only. |
| **Proxy** | object | Apify datacenter proxy | Default works for any reasonable run. |

### Output

Output renders in the run's **Output tab** with a dataset dropdown:

- **Reviews mode**: dropdown shows `Reviews` (review rows) and `Products` (per-product summary, one row per product).
- **Products mode**: dropdown shows `Reviews` (empty by design - products mode does not extract reviews) and `Products` (the discovered products with G2 catalog metadata).

Download from the Output tab dropdown as JSON, CSV, or Excel.

Note: on the Products dataset, `reviewsExtracted`, `completenessPct`, and `topCompetitors` are mined from review content. In Reviews mode they're fully populated; in Products mode `topCompetitors` is null while `reviewsExtracted` and `completenessPct` are `0` (no reviews were extracted).

#### Review row sample (`Reviews` tab in the Output dropdown)

Abbreviated — the full row has 32 fields including the `mode` marker. Sub-ratings are on a 0–10 scale (G2's internal precision; the overall `averageRating` on the products dataset is 0–5).

```json
{
  "mode": "reviews",
  "reviewId": "1234567",
  "reviewUrl": "https://www.g2.com/products/slack/reviews/slack-review-1234567",
  "productSlug": "slack",
  "productName": "Slack",
  "submittedAt": "2025-09-12T14:32:00+00:00",
  "reviewerName": "Sarah K.",
  "reviewerIndustry": "Marketing and Advertising",
  "reviewerRole": "Marketing Manager",
  "companySize": "Mid-Market",
  "reviewerCountry": "United States",
  "overallRating": 4,
  "easeOfUse": 8.5,
  "qualityOfSupport": 7.0,
  "reviewTitle": "Best team chat we've used",
  "pros": "Channels keep work organized; integrations with Jira and Salesforce are seamless.",
  "cons": "Notification volume is high until you tune it.",
  "problemsSolved": "Replaced 80% of internal email and consolidated cross-team coordination.",
  "recommendations": "Spend time setting up notification preferences early.",
  "didSwitchFromCompetitor": true,
  "previousCompetitors": "Microsoft Teams",
  "whySwitched": "Better thread management and a more responsive mobile app.",
  "isIncentivized": false,
  "helpfulVotes": 7,
  "extractedAt": "2026-05-21T12:00:00+00:00",
  "markdownContent": "### Slack review\n\n**Rating**: 4/5\n..."
}
```

#### Product row sample (`Products` tab - either per-product summary in Reviews mode, or discovered products in Products mode)

```json
{
  "slug": "slack",
  "name": "Slack",
  "id": 3437,
  "url": "https://www.g2.com/products/slack",
  "vendorName": "Slack Technologies",
  "type": "Software",
  "categoryNames": ["Business Instant Messaging"],
  "categoryPrimary": "Business Instant Messaging",
  "averageRating": 4.5,
  "starRating": 5,
  "reviewCount": 38966,
  "matchingFilterTotal": 38966,
  "reviewsExtracted": 1000,
  "completenessPct": 2.57,
  "topCompetitors": "Microsoft Teams, Google Chat, Discord, Zoom Workplace",
  "extractedAt": "2026-05-21T12:00:00+00:00"
}
```

> All timestamps are **UTC with explicit `+00:00`** offset.

### Pricing - how much does it cost to scrape G2 reviews

| Event | Price | Fires |
|---|---|---|
| Actor start | $0.01 | Once per run |
| Dataset row | $0.004 | Per output row - in Reviews mode this is per review row; in Products mode this is per discovered product. |

Platform usage (compute) is **included** in Apify's per-plan quota; no separate charge.

**Examples**:

- 100 **HubSpot** reviews (Reviews mode) = $0.01 + 100 × $0.004 = **$0.41**
- 1,000 **Slack** reviews (Reviews mode) = $0.01 + 1000 × $0.004 = **$4.01**
- 25-product **`CRM`** keyword search (Products mode) = $0.01 + 25 × $0.004 = **$0.11**
- 4 messaging competitors (Slack + Microsoft Teams + Google Chat + Discord) × 250 reviews each = $0.01 + 1000 × $0.004 = **$4.01**

New Apify users get **$5 platform credit**, which covers ~1,250 reviews at base tier.

### How to run this G2 reviews API on a schedule

This actor doubles as a G2 reviews API - call it from any HTTP client, the [Apify Python client](https://docs.apify.com/api/client/python), or the [Apify JS client](https://docs.apify.com/api/client/js). For incremental pulls:

1. Open the [Apify Schedules tab](https://docs.apify.com/platform/schedules) in your Console.
2. Set the cron (e.g., daily at 06:00 UTC).
3. In the schedule's input override, set `fromDate` to yesterday's date — the actor returns only reviews submitted on or after that.
4. (Optional) Wire an [Apify webhook](https://docs.apify.com/platform/integrations/webhooks) on `ACTOR.RUN.SUCCEEDED` to push results into Snowflake, BigQuery, Sheets, or your CRM.

### AI agents & RAG - using G2 reviews with LLMs

`markdownContent` is a self-contained markdown block per review, designed for direct ingestion into vector databases, RAG pipelines, and LLM context windows.

Examples using the [Apify Python client](https://docs.apify.com/api/client/python) and [Apify JS client](https://docs.apify.com/api/client/js):

**Python**

```python
from apify_client import ApifyClient

## Get your token from https://console.apify.com/account/integrations
client = ApifyClient("YOUR_APIFY_TOKEN")

run = client.actor("factden/g2-reviews-scraper").call(run_input={
    "startUrls": ["slack", "microsoft-teams"],
    "maxReviewsPerProduct": 100,
})

## Each markdownContent is a ready-to-embed chunk for your vector DB
for review in client.dataset(run["defaultDatasetId"]).iterate_items():
    chunk = review["markdownContent"]
    metadata = {"product": review["productSlug"], "rating": review["overallRating"]}
    print(metadata, chunk[:100], "...")
```

**JavaScript / TypeScript**

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

// Get your token from https://console.apify.com/account/integrations
const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });

const run = await client.actor('factden/g2-reviews-scraper').call({
  startUrls: ['slack', 'microsoft-teams'],
  maxReviewsPerProduct: 100,
});

// Each markdownContent is a ready-to-embed chunk for your vector DB
const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const review of items) {
  const metadata = { product: review.productSlug, rating: review.overallRating };
  console.log(metadata, review.markdownContent.slice(0, 100), '...');
}
```

<p align="center"><img src="https://raw.githubusercontent.com/factden/apify-actor-assets/main/g2-reviews-scraper/05-ai-ingest-markdown.png?v=2" width="1300" alt="G2 review converted to LLM-ready markdown content with rating, reviewer, company, pros, cons, problems solved, ready for direct ingestion into a vector store or RAG pipeline"></p>

**Wedge fields glossary** - what AI agents filter / chunk on:

| Field | What it means | Why an AI agent cares |
|---|---|---|
| `topCompetitors` | Top 10 most-cited competitors per product, ranked by mention count | Battlecard generation, competitive-intel agents |
| `previousCompetitors` | Named products the reviewer switched from | Migration-trend analysis, win-loss agents |
| `whySwitched` | Free-text reason for switching | Objection-handling, sales agents |
| `pros` / `cons` | Structured strengths and weaknesses | Sentiment-tagged retrieval, product-research agents |
| `markdownContent` | Self-contained per-review markdown | Vector-DB chunks, RAG pipelines, LLM prompts |

### Data sources & GDPR

Only public, listed-on-G2-product-page review data is extracted. No personal data is scraped beyond what's already publicly displayed (reviewer first name + last-initial, role, industry, company size, country). Reviewers' email addresses, full last names, account info, and any private fields are never accessed. You are responsible for downstream compliance with G2's terms of service and any applicable data-protection regulations in your jurisdiction.

### FAQ

**How much does it cost to scrape 10,000 G2 reviews?**
$0.01 + 10,000 × $0.004 = **$40.01** (one run start + 10,000 review rows). Apify's $5 free credit covers ~1,250 reviews.

**Can I filter by date?**
Yes. `From date` and `To date` accept YYYY-MM-DD and filter at scrape time. Cheaper than downloading everything and filtering after.

**What if a G2 product slug was renamed?**
The actor auto-resolves renamed slugs via fuzzy matching. The canonical slug appears as the `slug` field on the products dataset row (whether or not it matches the input), with a warning logged when a rename was applied. A 0.6 similarity floor prevents wrong substitutions.

**Can I run this on a schedule?**
Yes. Apify supports schedules and webhooks; use `From date` set to the previous run's start date for incremental runs.

**Why is `reviewerRole` null for some reviews?**
G2 makes the role field optional on the review form. About 48% of reviewers skip it.

**Does this work for products with thousands of reviews?**
Yes. Slack has ~39k reviews; you can extract them all in one run (set `maxReviewsPerProduct` to 50000). Expect ~12 minutes and ~$156 at base tier. Throughput is ~60 reviews/sec sustained.

**Can I export G2 reviews to CSV or Excel?**
Yes. The Output tab offers JSON, CSV, and Excel downloads on every dataset. The `Overview` view is laid out in customer-eye column order so it imports cleanly into Sheets / Excel.

**Is scraping G2 legal?**
This actor extracts only **public** review data already displayed on G2 product pages - no logins, no private fields, no personal data beyond what G2 itself publishes. You are responsible for complying with G2's terms of service and any applicable data-protection regulations in your jurisdiction. If in doubt, consult counsel.

**Can I monitor G2 reviews continuously?**
Yes. Use Apify [Schedules](https://docs.apify.com/platform/schedules) + [Webhooks](https://docs.apify.com/platform/integrations/webhooks) to run the actor daily with `fromDate` set to yesterday, and push new reviews into Slack / your CRM / a warehouse.

**How fresh is G2 review data?**
**Real-time** - the actor hits G2's live pages on every run, not a cached copy. A review submitted to G2 minutes ago appears in the next run as soon as G2's own indexing picks it up (typically a 1-2 minute lag on G2's side, nothing on ours).

**Can I scrape G2 products and reviews in one workflow?**
Yes, by chaining two runs of the same actor: (1) run in **Products mode** with a search keyword (e.g. `CRM`) to discover the top N products and their G2 slugs, then (2) feed those slugs into a second run in **Reviews mode** to extract every review. Total cost: $0.004 per discovered product + $0.004 per review row. Wire the chain via Apify [task chaining](https://docs.apify.com/platform/actors/running/runs-and-builds) or a webhook.

### Changelog

#### 1.0 - Initial release (2026-05-21)

- 32 review-row keys (31 review fields + `mode` marker), semantically ordered for readability - including `markdownContent` for LLM/RAG ingestion.
- Per-product `topCompetitors` ranking - top 10 named competitors by mention count, unique to this Actor.
- 2 curated review views (Overview, AI ingest) + 1 product view (Overview, 11 columns - includes reviewsExtracted / completenessPct / topCompetitors which populate in Reviews mode; in Products mode `topCompetitors` is null and the two counters are `0`).
- Resolved competitor display names (`previousCompetitors`) - no opaque IDs, no manual lookup.
- Two modes: Reviews (extract reviews for given products) and Products (keyword discovery).
- Auto-resolve renamed G2 slugs with a 0.6 similarity floor.
- PPE pricing: $0.01 per run + $0.004 per row (unified across both modes - Reviews mode and Products mode price the same per row).

### Support & maintenance

**Actively maintained.** Updates pushed regularly — see the [Changelog](#changelog) section above. Bug reports are typically triaged within 1-2 business days.

- **Bug reports / feature requests**: use the **Issues** tab on this actor's [Apify Store page](https://apify.com/factden/g2-reviews-scraper/issues)
- **Private inquiries**: <hello@factden.com>

***

*Built by [factden](https://apify.com/factden) on the Apify platform. **Try the G2 Reviews Scraper free** with Apify's $5 monthly credit - covers ~1,250 reviews on first run.*

# Actor input Schema

## `mode` (type: `string`):

Pick the workflow:

- **Extract reviews** (default): get every public review for the products listed below. Writes review rows to the `Reviews` dataset and a per-product summary (incl. `topCompetitors`) to the `Products` dataset.
- **Discover products**: find the top N products on G2 matching a search query. Writes product rows to the `Products` dataset; the `Reviews` dataset stays empty.

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

Each entry is either a full G2 URL (`https://www.g2.com/products/<slug>` or `.../reviews`) or a bare canonical slug (`slack`, `microsoft-teams` — lowercase, hyphens, no spaces). Up to 100 products per run.

## `maxReviewsPerProduct` (type: `integer`):

Hard ceiling per product (1–50,000). Default 100 ≈ $0.41 per run, fits inside the $5 free credit. Raise for the full pull: 1,000 reviews ≈ $4.01, 10,000 ≈ $40.01.

## `fromDate` (type: `string`):

Only return reviews submitted on or after this date. Format: YYYY-MM-DD. Leave blank for no lower bound.

## `toDate` (type: `string`):

Only return reviews submitted on or before this date. Format: YYYY-MM-DD. Leave blank for no upper bound.

## `minRating` (type: `integer`):

Only return reviews with an overall rating ≥ this value. Default 1 = include all detractors.

## `maxRating` (type: `integer`):

Only return reviews with an overall rating ≤ this value. Default 5 = include all promoters.

## `sortReviews` (type: `string`):

How to order extracted reviews. `newest` (default) = most recent first. `rating_low` is the fastest path to negative-review pain-point mining. `helpful` surfaces the reviews G2 readers themselves found most useful.

## `verifiedReviewer` (type: `boolean`):

When on, only reviews from verified G2 reviewers are returned (filters out the vendor-submitted set). Default off = include all.

## `searchQuery` (type: `string`):

Keyword used to look up products on G2 (e.g. `communication`, `CRM`, `project management`, `saas`). 2–200 characters.

## `maxProducts` (type: `integer`):

How many products to return (1–1,000). Each product row costs $0.004.

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

Defaults to Apify Proxy datacenter group, included in your Apify plan's monthly proxy quota (~9 GB free on Personal; this actor uses under 50 MB per 36k-review extraction). Switch to residential if you hit IP issues.

## Actor input object example

```json
{
  "mode": "reviews",
  "startUrls": [
    "https://www.g2.com/products/slack/reviews",
    "microsoft-teams"
  ],
  "maxReviewsPerProduct": 100,
  "minRating": 1,
  "maxRating": 5,
  "sortReviews": "newest",
  "verifiedReviewer": false,
  "searchQuery": "communication",
  "maxProducts": 25,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": []
  }
}
```

# Actor output Schema

## `reviews` (type: `string`):

Per-review rows with ratings, 6 sub-ratings, named switching-from competitors, structured pros/cons/problems-solved/recommendations, reviewer firmographics, and an LLM-ready markdownContent block per row. Populated only in Reviews mode (Products mode does not extract reviews).

## `products` (type: `string`):

Per-product rows with topCompetitors ranking, categoryPrimary, averageRating, reviewCount, completenessPct, url. Populated in both modes: Reviews mode writes 1 summary row per slug; Products mode writes the keyword-search results.

# 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 = {
    "mode": "reviews",
    "startUrls": [
        "https://www.g2.com/products/slack/reviews",
        "microsoft-teams"
    ],
    "maxReviewsPerProduct": 100,
    "minRating": 1,
    "maxRating": 5,
    "sortReviews": "newest",
    "verifiedReviewer": false,
    "searchQuery": "communication",
    "maxProducts": 25,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": []
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("factden/g2-reviews-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 = {
    "mode": "reviews",
    "startUrls": [
        "https://www.g2.com/products/slack/reviews",
        "microsoft-teams",
    ],
    "maxReviewsPerProduct": 100,
    "minRating": 1,
    "maxRating": 5,
    "sortReviews": "newest",
    "verifiedReviewer": False,
    "searchQuery": "communication",
    "maxProducts": 25,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": [],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("factden/g2-reviews-scraper").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "mode": "reviews",
  "startUrls": [
    "https://www.g2.com/products/slack/reviews",
    "microsoft-teams"
  ],
  "maxReviewsPerProduct": 100,
  "minRating": 1,
  "maxRating": 5,
  "sortReviews": "newest",
  "verifiedReviewer": false,
  "searchQuery": "communication",
  "maxProducts": 25,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": []
  }
}' |
apify call factden/g2-reviews-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=factden/g2-reviews-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "G2 Reviews & Products Scraper | AI, Competitor Intel (2026)",
        "description": "Scrape G2 reviews and products in real-time. 32 fields: 6 sub-ratings, switching competitors, structured pros/cons, LLM-ready markdown. Top 10 competitors ranked per product. Built for market research, competitive intelligence, sales enablement. No login, no proxy, no anti-bot. $4 per 1,000 rows.",
        "version": "1.0",
        "x-build-id": "vpUg2zk6ketYKC4Eg"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/factden~g2-reviews-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-factden-g2-reviews-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/factden~g2-reviews-scraper/runs": {
            "post": {
                "operationId": "runs-sync-factden-g2-reviews-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/factden~g2-reviews-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-factden-g2-reviews-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "mode": {
                        "title": "Mode",
                        "enum": [
                            "reviews",
                            "products"
                        ],
                        "type": "string",
                        "description": "Pick the workflow:\n- **Extract reviews** (default): get every public review for the products listed below. Writes review rows to the `Reviews` dataset and a per-product summary (incl. `topCompetitors`) to the `Products` dataset.\n- **Discover products**: find the top N products on G2 matching a search query. Writes product rows to the `Products` dataset; the `Reviews` dataset stays empty.",
                        "default": "reviews"
                    },
                    "startUrls": {
                        "title": "G2 product URLs or slugs",
                        "minItems": 0,
                        "maxItems": 100,
                        "type": "array",
                        "description": "Each entry is either a full G2 URL (`https://www.g2.com/products/<slug>` or `.../reviews`) or a bare canonical slug (`slack`, `microsoft-teams` — lowercase, hyphens, no spaces). Up to 100 products per run.",
                        "items": {
                            "type": "string",
                            "pattern": "^(https?://([a-zA-Z0-9-]+\\.)?[gG]2\\.com/products/[a-zA-Z0-9-]{2,50}([/?#].*)?$|[a-zA-Z0-9-]{2,50})$"
                        }
                    },
                    "maxReviewsPerProduct": {
                        "title": "Max reviews per product",
                        "minimum": 1,
                        "maximum": 50000,
                        "type": "integer",
                        "description": "Hard ceiling per product (1–50,000). Default 100 ≈ $0.41 per run, fits inside the $5 free credit. Raise for the full pull: 1,000 reviews ≈ $4.01, 10,000 ≈ $40.01.",
                        "default": 100
                    },
                    "fromDate": {
                        "title": "From date",
                        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                        "type": "string",
                        "description": "Only return reviews submitted on or after this date. Format: YYYY-MM-DD. Leave blank for no lower bound."
                    },
                    "toDate": {
                        "title": "To date",
                        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                        "type": "string",
                        "description": "Only return reviews submitted on or before this date. Format: YYYY-MM-DD. Leave blank for no upper bound."
                    },
                    "minRating": {
                        "title": "Minimum rating (1–5)",
                        "minimum": 1,
                        "maximum": 5,
                        "type": "integer",
                        "description": "Only return reviews with an overall rating ≥ this value. Default 1 = include all detractors.",
                        "default": 1
                    },
                    "maxRating": {
                        "title": "Maximum rating (1–5)",
                        "minimum": 1,
                        "maximum": 5,
                        "type": "integer",
                        "description": "Only return reviews with an overall rating ≤ this value. Default 5 = include all promoters.",
                        "default": 5
                    },
                    "sortReviews": {
                        "title": "Sort reviews by",
                        "enum": [
                            "newest",
                            "helpful",
                            "rating_high",
                            "rating_low"
                        ],
                        "type": "string",
                        "description": "How to order extracted reviews. `newest` (default) = most recent first. `rating_low` is the fastest path to negative-review pain-point mining. `helpful` surfaces the reviews G2 readers themselves found most useful.",
                        "default": "newest"
                    },
                    "verifiedReviewer": {
                        "title": "Verified reviewers only",
                        "type": "boolean",
                        "description": "When on, only reviews from verified G2 reviewers are returned (filters out the vendor-submitted set). Default off = include all.",
                        "default": false
                    },
                    "searchQuery": {
                        "title": "Search query",
                        "minLength": 2,
                        "maxLength": 200,
                        "type": "string",
                        "description": "Keyword used to look up products on G2 (e.g. `communication`, `CRM`, `project management`, `saas`). 2–200 characters."
                    },
                    "maxProducts": {
                        "title": "Max products",
                        "minimum": 1,
                        "maximum": 1000,
                        "type": "integer",
                        "description": "How many products to return (1–1,000). Each product row costs $0.004.",
                        "default": 25
                    },
                    "proxyConfiguration": {
                        "title": "Proxy",
                        "type": "object",
                        "description": "Defaults to Apify Proxy datacenter group, included in your Apify plan's monthly proxy quota (~9 GB free on Personal; this actor uses under 50 MB per 36k-review extraction). Switch to residential if you hit IP issues.",
                        "default": {
                            "useApifyProxy": true,
                            "apifyProxyGroups": []
                        }
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
