ScraperCity logo

Integration Guide

ScraperCity + GoHighLevel

Scrape B2B leads from Apollo, Google Maps, or the Lead Database and push them directly into GoHighLevel as contacts. Leads land in your GHL pipelines with name, email, phone, company, and custom fields - ready for workflows and outreach.

How It Works

ScraperCity provides an API that returns B2B contact data - emails, phone numbers, job titles, company names, LinkedIn URLs. GoHighLevel provides an API that creates contacts in your CRM. Connect the two and you have an automated lead pipeline that fills your GHL sub-accounts with fresh prospects.

The GoHighLevel API v2 is a REST API built around Private Integration Tokens and OAuth 2.0. For the ScraperCity use case - pushing leads into a single sub-account or a set of client sub-accounts - a Private Integration Token is the simplest authentication method. You generate one in your GHL settings, scope it to contacts, and use it as a Bearer token. No expiry management, no refresh token loops.

The flow works for any ScraperCity data source: scrape Apollo contacts for $0.0039/lead, pull local businesses from Google Maps for $0.01/place, find business emails for $0.05/contact, or query the Lead Database for instant results. Map the output fields to GHL contact fields and POST them to the API.

Before You Start: What You Need

How to Get Your GoHighLevel API Token

GHL no longer issues plain API keys for new accounts. The current authentication method for internal integrations is the Private Integration Token. Here is how to generate one:

  1. Log into GoHighLevel and open the sub-account (or agency account) where you want to create contacts.
  2. Go to Settings, then scroll to Integrations, then click Private Integrations. If you do not see this option, enable it in the Labs settings first.
  3. Click Create new Integration. Give it a name (e.g. "ScraperCity Lead Push") and a description.
  4. Under Scopes, enable contacts.write and contacts.readonly. Only select the scopes your integration actually needs - this keeps the token secure.
  5. Click Save. Copy the token immediately - you cannot view it again after closing this screen.
  6. Use the token as your Bearer token in all GHL API requests. It does not expire on a short cycle the way OAuth access tokens do.

GHL recommends rotating Private Integration tokens every 90 days. When you rotate, you get a 7-day window where both the old and new tokens work - enough time to update your scripts without downtime.

Setup

1

Create a Private Integration in GHL

In your GoHighLevel sub-account, go to Settings, then Integrations, then Private Integrations. Create a new one with the contacts.write scope enabled. Save the token - you will not be able to view it again.

2

Pull leads from ScraperCity

Query any ScraperCity endpoint. Here is an example using the Lead Database (requires the $649/mo plan):

curl -X GET "https://app.scrapercity.com/api/v1/database/leads?title=CEO&industry=real%20estate&country=United%20States&hasEmail=true&limit=50" \
  -H "Authorization: Bearer YOUR_SCRAPERCITY_KEY"

Or scrape Apollo contacts (available on all plans, results in 11-48+ hours):

curl -X POST "https://app.scrapercity.com/api/v1/apollo/scrape" \
  -H "Authorization: Bearer YOUR_SCRAPERCITY_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "titles": ["CEO", "Founder"],
    "industries": ["Real Estate"],
    "locations": ["United States"],
    "limit": 100
  }'
3

Push each lead to GHL

For each contact in the response, POST to the GoHighLevel Contacts API. The Version header is required for all GHL API v2 calls:

curl -X POST "https://services.leadconnectorhq.com/contacts/" \
  -H "Authorization: Bearer YOUR_GHL_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Version: 2021-07-28" \
  -d '{
    "firstName": "Jane",
    "lastName": "Smith",
    "email": "[email protected]",
    "phone": "+15551234567",
    "companyName": "Acme Corp",
    "locationId": "YOUR_LOCATION_ID",
    "tags": ["scraped-apollo"],
    "customFields": [
      { "key": "job_title", "value": "CEO" },
      { "key": "linkedin_url", "value": "https://linkedin.com/in/janesmith" }
    ]
  }'
4

Trigger a GHL workflow (optional)

Create a workflow in GHL triggered by the tag you applied (e.g. "scraped-apollo"). The workflow can assign leads to a pipeline stage, start an email/SMS sequence, or notify your team via Slack.

Field Mapping: ScraperCity to GoHighLevel

ScraperCity returns a consistent JSON structure across all lead sources. Here is how those fields map to GHL contact fields and where to put extra data:

ScraperCity FieldGHL Contact FieldNotes
first_namefirstNameTop-level field
last_namelastNameTop-level field
emailemailTop-level field
phonephoneUse E.164 format (+1...)
company_namecompanyNameTop-level field
title / job_titlecustomFields[key="job_title"]Create custom field first
linkedin_urlcustomFields[key="linkedin_url"]Create custom field first
citycityTop-level field
statestateTop-level field
countrycountryTop-level field
industrycustomFields[key="industry"]Create custom field first
websitewebsiteTop-level field
employee_countcustomFields[key="employee_count"]Store as text or number field

Custom fields must be created in GHL before you reference them. Go to Settings - Custom Fields in your sub-account and add each field. GHL will assign each a key that you use in the customFields array.

Automate with n8n, Zapier, or a Script

You do not need to write a custom server to run this pipeline. Three common approaches work well depending on your technical comfort level:

Option A - Node.js / Python script

The most flexible option. Pull leads from ScraperCity, loop through the results, and POST each one to GHL. Add a small delay between requests to stay under the GHL burst limit (100 requests per 10 seconds). Here is a minimal Node.js example:

const leads = await fetch('https://app.scrapercity.com/api/v1/database/leads?title=CFO&hasEmail=true&limit=100', {
  headers: { Authorization: 'Bearer YOUR_SCRAPERCITY_KEY' }
}).then(r => r.json());

for (const lead of leads.data) {
  await fetch('https://services.leadconnectorhq.com/contacts/', {
    method: 'POST',
    headers: {
      Authorization: 'Bearer YOUR_GHL_TOKEN',
      'Content-Type': 'application/json',
      Version: '2021-07-28'
    },
    body: JSON.stringify({
      firstName: lead.first_name,
      lastName: lead.last_name,
      email: lead.email,
      phone: lead.phone,
      companyName: lead.company_name,
      locationId: 'YOUR_LOCATION_ID',
      tags: ['scraped-database'],
      customFields: [
        { key: 'job_title', value: lead.title },
        { key: 'linkedin_url', value: lead.linkedin_url }
      ]
    })
  });
  // Pause 150ms between requests to stay under GHL burst limit
  await new Promise(r => setTimeout(r, 150));
}

Option B - n8n workflow

In n8n, use an HTTP Request node to call the ScraperCity endpoint. Connect it to a second HTTP Request node configured as a POST to https://services.leadconnectorhq.com/contacts/ with the GHL token in the Authorization header and Version: 2021-07-28 as a second header. Use the Split In Batches node between the two to pace requests and respect the GHL rate limit. You can schedule the workflow to run on a cron - every morning, every hour, or after a ScraperCity webhook fires.

Option C - Zapier

Zapier has a native GoHighLevel integration. Use a Webhook trigger (or a Schedule trigger) to kick off a Zap, call the ScraperCity API via a Zapier Webhooks step to pull leads, then use the GoHighLevel "Create/Update Contact" action to push each one. Zapier handles the auth handshake for GHL natively - you just connect your GHL account and map fields. This works well for low-to-medium volume (a few hundred leads per run) without writing any code.

For Agencies: Filling Multiple Sub-Accounts

If you run a GoHighLevel agency serving multiple clients, ScraperCity lets you fill client sub-accounts with targeted leads at scale. Scrape leads matching each client's ICP, push them into the right sub-account using that location's ID, and let GHL workflows handle the nurture. Apollo leads cost $0.0039 each - at that price, loading 10,000 prospects into a client's pipeline costs under $40.

The GHL API supports both Location Level Access (for a single sub-account) and Agency Level Access (for managing data across the whole agency). For most lead-push use cases, a per-sub-account Private Integration Token is the right choice - it scopes access tightly to that client's data and keeps things clean.

A practical agency workflow looks like this:

  1. For each client, define the ICP parameters: job titles, industries, location, company size.
  2. Run a ScraperCity query (Apollo or Lead Database) with those parameters. Save the runId returned by the API.
  3. Poll the ScraperCity status endpoint until the run is complete, then download the CSV or consume the JSON directly.
  4. Loop through the leads and POST each to the client's GHL sub-account using that sub-account's locationId and Private Integration Token.
  5. Apply a source tag (e.g. "apollo-jan-batch") so the client and your team can track where each lead came from.
  6. GHL workflows fire automatically based on the tag - the client's nurture sequence starts without any manual intervention.

On the $149/mo ScraperCity plan you can run this for multiple clients simultaneously. On the $649/mo plan you also get access to the Lead Database endpoint, which returns results instantly - no waiting for a scrape to complete.

Common Use Cases

Local business outreach for service-area clients

Scrape Google Maps for businesses matching a category in a city ($0.01/place). Each result includes the business name, phone, website, and often an email. Push them into a GHL sub-account as contacts and trigger a cold outreach workflow. Google Maps leads are available on all plans and return in 5-30 minutes.

SaaS and B2B prospecting via Apollo

Target specific job titles at companies in a defined industry. Apollo leads include work email, phone, LinkedIn, company size, and funding stage. At $0.0039/lead, you can fill an entire GHL pipeline with 1,000 vetted prospects for under $4. Apollo scrapes complete in 11-48+ hours.

E-commerce store owners for agency pitches

Use the Store Leads endpoint to find Shopify and WooCommerce stores ($0.0039/lead, instant). Results include store owner contact info, revenue estimates, and tech stack. Push them into GHL with a tag like "shopify-prospect" and trigger a workflow for your agency's pitch sequence.

Real estate investor outreach

Pull real estate agent contacts from Zillow Agents or commercial listings from Crexi ($0.029/listing). Map agent name, phone, email, and brokerage into GHL contact fields. Tag by region so you can run geo-targeted SMS or email sequences.

Lead enrichment on existing GHL contacts

Export a list of GHL contacts that are missing phone numbers. Run each through the ScraperCity Mobile Finder ($0.25/input) to append mobile numbers, then update the contacts in GHL via the PATCH /contacts/{id} endpoint. Enriched contacts respond better to call-based workflows.

Troubleshooting

401 Unauthorized from GHL API

Your Private Integration Token is missing, expired, or does not have the right scope. Check that the token is included in the Authorization: Bearer header (not a query parameter). Confirm the token has contacts.write scope enabled in your GHL Private Integrations settings. Note that GHL recommends rotating tokens every 90 days - if it has been a while, generate a fresh one.

422 Unprocessable Entity on contact creation

This usually means a required field is missing or a field value is in the wrong format. The most common culprits: locationId is missing or wrong, a phone number is not in E.164 format (+15551234567), or a custom field key does not match what exists in GHL. Double-check the locationId in your GHL sub-account settings and verify custom field keys under Settings - Custom Fields.

429 Too Many Requests from GHL API

You have hit the burst rate limit of 100 requests per 10 seconds. Add a delay between API calls - 150ms between each POST is a safe pace for batches of any size. Watch the X-RateLimit-Remaining and X-RateLimit-Daily-Remaining headers in the GHL response to monitor your quota in real time.

Missing Version header error from GHL

All GHL API v2 calls require the Version: 2021-07-28 header. If you omit it, some endpoints return errors or unexpected results. Make sure this header is present on every request.

ScraperCity returns no results

If a Lead Database query returns zero leads, try broadening the filters - remove the hasEmail=true constraint, widen the industry, or remove the location filter. For Apollo scrapes, results arrive in 11-48+ hours - poll the status endpoint rather than assuming the run failed. You can find the webhook setup at app.scrapercity.com/dashboard/webhooks to get notified when results are ready.

Duplicate contacts appearing in GHL

GHL will create a duplicate if a contact with the same email already exists and you do not use the upsert endpoint. Consider using POST /contacts/upsert instead of plain POST /contacts/. The upsert endpoint matches on email and updates the existing record rather than creating a new one.

Performance Tips

GoHighLevel API v2 Quick Reference

For reference, here are the key GHL API v2 details you need for this integration:

Base URL: https://services.leadconnectorhq.com

Create contact: POST /contacts/

Upsert contact: POST /contacts/upsert

Update contact: PUT /contacts/{contactId}

Auth header: Authorization: Bearer YOUR_TOKEN

Version header: Version: 2021-07-28

Burst limit: 100 requests / 10 seconds

Daily limit: 200,000 requests / day

Rate limit headers: X-RateLimit-Remaining, X-RateLimit-Daily-Remaining

Full docs: marketplace.gohighlevel.com/docs

FAQ

Get API access to ScraperCity: