What the G2 scraper collects
Give it a G2 category slug, a product slug or any g2.com URL and it returns a flat list of software products: title, G2 category, the 0-5 star rating and the 0-10 G2 score, review count, G2's product/vendor/category ids, image and link. Prices from each product's /pricing page are opt-in; output is JSON or CSV with a run-metadata sidecar.
Category listing
Input: A category slug or /categories/{slug} URLOne row per product card with the 0-5 rating, review count, category, product type and G2's product, vendor and category ids. Paginated with ?page=N.
Product page
Input: A product slug or /products/{slug}/reviews URLOne row for the product with G2's 0-10 composite score, review count, title and image.
Pricing page
Input: A /products/{slug}/pricing URLThe product's lowest parsed pricing tier with currency and price_source; nothing else is invented.
Category with pricing
Input: A category slug plus --with-pricingA category listing where each collected product's /pricing page is also fetched to fill price and currency, up to --pricing-limit.
From zero to G2 data in 3 steps
Install
Clone the repository and install one browser engine. Python 3.9+.
$ git clone https://github.com/2scraper/g2-scraper.git && cd g2-scraper $ python3 -m venv .venv && . .venv/bin/activate $ pip install -r requirements-playwright.txt && playwright install chromium $ cp .env.example .env
Run a scraper
Pick what you need and run it. Every flag is documented in the README.
$ python3 playwright_scraper.py --category crm --max-pages 3 --format json --out g2_results.json$ python3 playwright_scraper.py --product hubspot-sales-hub$ python3 playwright_scraper.py --url "https://www.g2.com/products/hubspot-sales-hub/pricing"$ python3 playwright_scraper.py --category crm --max-results 10 --with-pricing --pricing-limit 10Get structured data
Rows land in JSON or CSV (
--format), with a.meta.jsonsidecar recording status, pages fetched and why the run stopped.
G2 data fields
21 columns per row in a predictable schema. The most useful ones:
| Field | What it holds |
|---|---|
sku | The product's URL slug — joins listing and product rows |
title | Product name |
category | G2 category |
rating_5 | 0-5 star rating from a listing card |
rating_10 | G2's own 0-10 composite score from a product page |
review_count | Number of reviews |
review_count_source | listing_card or json_ld — which page the count came from |
price | Lowest parsed pricing tier (with --with-pricing or a /pricing URL) |
currency | Currency of that price |
product_id | G2's numeric product id |
product_uuid | G2's product UUID |
vendor_id | G2's numeric vendor id |
category_id | G2's numeric category id |
product_type | G2's product type, e.g. Software |
product_url | Link to the product's reviews page |
image_url | Product logo URL |
[
{
"sku": "placeholder-crm-suite",
"source": "g2.com",
"category": "Example CRM",
"title": "[FICTIONAL SAMPLE ROW — not a live capture] Placeholder CRM Suite",
"brand": null,
"price": null,
"currency": null,
"price_source": null,
"product_url": "https://www.g2.com/products/placeholder-crm-suite/reviews",
"image_url": "https://images.g2crowd.com/uploads/fictional/placeholder-crm-suite.png",
"scraped_at": "2026-09-22T00:00:00Z",
"rating_5": 4.4,
"rating_10": null,
"review_count": 12345,
"review_count_source": "listing_card",
"product_id": 900001,
"product_uuid": "00000000-0000-4000-8000-000000000001",
"product_slug": "placeholder-crm-suite",
"vendor_id": 800001,
"category_id": 700001,
"product_type": "Software"
},
{
"sku": "fictional-helpdesk-cloud",
"source": "g2.com",
"category": "Example CRM",
"title": "[FICTIONAL SAMPLE ROW — not a live capture] Fictional Helpdesk Cloud",
"brand": null,
"price": null,
"currency": null,
"price_source": null,
"product_url": "https://www.g2.com/products/fictional-helpdesk-cloud/reviews",
"image_url": null,
"scraped_at": "2026-09-22T00:00:00Z",
"rating_5": null,
"rating_10": null,
"review_count": null,
"review_count_source": null,
"product_id": 900002,
"product_uuid": "00000000-0000-4000-8000-000000000002",
"product_slug": "fictional-helpdesk-cloud",
"vendor_id": 800002,
"category_id": 700001,
"product_type": "Software"
}
]Illustrative rows that show the schema — labelled fictional in the repo, not a live capture. sample_output.json.
Handles what breaks naive G2 scrapers
Two rating scales, never merged
The 0-5 star rating from a listing and G2's 0-10 score from a product page go in separate columns; nothing averages or converts between them.
One --url, three parsers
Category, product and pricing URLs are auto-routed to the matching parser, and anything else is refused with exit 2 before a request is made.
robots.txt honoured up front
G2's stricter rule group is applied by default, and a disallowed --url is refused before any request rather than fetched and discarded.
Nothing guessed
brand stays empty because G2 publishes only a vendor id, and an unreadable pricing page leaves price empty — it never reads as 'free'.
Scraping infrastructure included
The same tested core runs every 2scraper repository, so the hard parts work the same way on every site.
CAPTCHA handling
Detects the challenge a page really serves and, with a 2Captcha key, solves it only when it blocks the data — a capped number of solves per page.
Proxy rotation
Single proxy or a pool from a file, rotated on blocks with a fresh browser per exit. Credentials stay out of argv and logs.
Fingerprints
Optional complete device identity from the 2Captcha Fingerprint API — user agent, client hints, locale and timezone that agree with each other.
Scraping Browser API
Point --cdp-endpoint at a managed Chromium with its own exit country — no browser infrastructure to run yourself.
Honest run metadata
Every run writes a .meta.json sidecar and distinct exit codes: complete, blocked, empty and partial are never confused, and a failed run never overwrites good data.
Diff two runs
diff_runs.py compares two complete G2 snapshots by id — new, removed and changed rows for monitoring.
What teams do with G2 data
Competitive landscape mapping
Pull every product in a G2 category with ratings, review counts and vendor ids to see who leads a market.
Rating and review-count tracking
Diff runs over time to watch rating and review-count movement for your product and competitors.
SaaS pricing research
Collect the lowest published pricing tier across a category with --with-pricing.
Lead lists for B2B
Build lists of software vendors per category using G2's own product and vendor ids as stable keys.
Free to run. Pay only for what the site requires.
Free to run · paid add-ons optional
No 2Captcha account, proxy or key is required: the default is an ordinary local headless Chromium. G2 can show a DataDome wall, which the scraper reports honestly as blocked (exit 3); captcha solving attempts 2Captcha's DataDomeSliderTask but needs a proxy to do so. Proxies, fingerprints, the Scraping Browser API and the Scraper API are opt-in for volume, a specific exit country, or running through a managed remote browser.
Optional 2Captcha services — captcha solving, the Scraping Browser API, residential proxies and fingerprints — work behind one key.
Good to know
- Review text and author names are not collected; brand is always empty.
- Pricing is best-effort text matching, since G2 publishes no pricing JSON-LD.
- Solving a DataDome slider requires --proxy or --proxy-file.
2scraper vs. hosted scraper APIs
| 2scraper | Typical hosted API | |
|---|---|---|
| Code | Open source, MIT — read and patch it | Closed |
| Cost | Free; optional services billed only when used | Subscription or per request / per result |
| Runs on | Your machine, server or CI | The vendor's infrastructure |
| Output | JSON/CSV files + run metadata | API responses |
| When the site changes | Fix it yourself or open an issue / PR | Wait for the vendor |
G2 scraper FAQ
Do I need a 2Captcha key or a proxy?
Not to run it — the default is a local headless Chromium with no account. A proxy is needed if you want a DataDome slider solved, and helps with volume.
Which G2 pages are supported?
Category listings (/categories/{slug}), product review pages (/products/{slug}/reviews) and pricing pages (/products/{slug}/pricing).
Does it scrape review text?
No. Review text and author names are not in the output; it collects product-level ratings and review counts.
Why are rating_5 and rating_10 both there?
G2 shows a 0-5 star rating on listing cards and a 0-10 composite score on product pages. They are different measures and are kept apart.
What formats does it write?
JSON or CSV, plus a <out>.meta.json sidecar with status, failed pages and counts. A blocked or empty run writes nothing, so a previous good output is never overwritten.
Is scraping G2 legal?
It reads public pages and honours robots.txt by default. Follow G2's terms and the law where you operate.