HubSpot Email Checker · Bulk Login Detection avatar

HubSpot Email Checker · Bulk Login Detection

Pricing

from $4.99 / 1,000 results

Go to Apify Store
HubSpot Email Checker · Bulk Login Detection

HubSpot Email Checker · Bulk Login Detection

Bulk-check whether email addresses have a HubSpot login. Paste a list, get one structured row per email: registered, HTTP status, and raw HubSpot response. No manual lookup needed.

Pricing

from $4.99 / 1,000 results

Rating

0.0

(0)

Developer

Corentin Robert

Corentin Robert

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

18 hours ago

Last modified

Share

HubSpot Email Registration Checker

Bulk-check whether email addresses already have a HubSpot login — the same signal HubSpot’s own login page uses before asking for a password. You paste a list; you get one dataset row per email with a clear yes / no / couldn’t tell outcome, plus raw fields from HubSpot so you can audit or export to Sheets or your CRM.

This Actor is not an official HubSpot product or documented API. HubSpot’s web app can change, rate-limit, or return new status codes. Use it only for legitimate purposes (e.g. contacts you’re allowed to verify, internal list hygiene). Do not use it for aggressive enumeration or address guessing. Review HubSpot’s Terms of Service and applicable law.


Table of contents


Why use this?

Without this ActorWith this Actor
You open HubSpot login (or support) one contact at a timeYou paste hundreds or thousands of emails in one run
You only get a vague “try signing up” feelingYou get a structured row per address: registered, HTTP code, HubSpot status/message when available
Hard to reconcile in a spreadsheetCSV / JSON export from Apify Dataset, timestamps (checkedAt) for auditing

Typical use cases

  • List hygiene before invites or onboarding: avoid inviting addresses that already have a portal login.
  • Sales / marketing alignment: spot-check whether a batch of work emails is already tied to HubSpot logins.
  • Ops / compliance checks you’re entitled to run on your own or consented data — not for cold guessing.

Important caveat: registered: true means HubSpot returned a signal consistent with “a login path exists” for that email — not necessarily that the person actively uses HubSpot today. Edge cases (SSO-only, suspended accounts, special statuses) exist; spot-check critical rows manually.


How it works (under the hood)

  1. Input — You provide a list of email strings. Each line is trimmed; obviously invalid formats are skipped (no HTTP call) and still appear in the dataset with an error message.

  2. One email at a time — The Actor processes addresses sequentially (one request, then the next). There is a short pause between calls to behave politely. Very large lists are supported (up to 10,000 emails per run).

  3. Same endpoint as the login UI — For each valid email, the Actor sends an HTTP POST to HubSpot’s public app endpoint
    /api/login-requirements/login
    with the same static app query parameters the Login UI uses (version is pinned in code; if HubSpot changes their bundle, the Actor may need an update).

  4. Browser-like HTTP client — Requests use got-scraping (realistic headers, HTTP/2 when available). Apify Proxy is strongly recommended because HubSpot is often behind Cloudflare; datacenter or bare IPs frequently get 403 or HTML challenge pages instead of JSON.

  5. Retries — Transient errors (429, 408, 5xx) are retried a few times with short backoff.

  6. Interpretation — The JSON body is parsed and mapped to registered / hubspotStatus / hubspotMessage / correlationId (see Understanding your results). Non-JSON bodies (e.g. Cloudflare HTML) produce registered: null and a short error string in the dataset — not a wall of HTML.

  7. Output — Each check is pushData’d as one dataset item. A RUN_LOG key in the default key-value store shows progress (checked / total). After a run on Apify, the Output tab also lists API links (dataset JSON, results view, run metadata) when configured in the Actor’s output schema.


Quick start on Apify

  1. Open the Actor in the Apify Console.
  2. Under Input, paste your emails (one per line).
  3. Under Proxy, leave Apify proxy enabled (default). If you still see 403 / Cloudflare in the dataset, switch to RESIDENTIAL proxy group or see Proxy, Cloudflare, and 403 errors.
  4. Click Start.
  5. Open Dataset when the run finishes (or while it runs — rows appear as they are written). Export JSON or CSV as needed.

For CLI developers: use apify login then apify run so proxy and storage behave like the cloud.


Understanding your results

registeredWhat it usually means
falseHubSpot returned a “no such user” style outcome for that check (same family of signal as INVALID_USER on the login flow). Treat as: no HubSpot login for that email for this check.
trueHubSpot did not return the plain “no user” path; the payload suggests some login or account-related path exists. Verify important addresses yourself (SSO-only, suspended, or new status codes can occur).
nullCould not decide: network error, 403 / Cloudflare, timeout, or unexpected JSON. Read error and httpStatus on that row; fix proxy or retry.

Special case: registered: true with hubspotStatus: null — JSON was interpreted as “likely known user” from other fields (e.g. hints in the payload) without a top-level status. Treat as heuristic yes; double-check if it matters.


Proxy, Cloudflare, and 403 errors

HubSpot’s app is protected by Cloudflare. If you run without a working proxy, you often get HTTP 403 and an HTML challenge page — the Actor stores a short explanation in error, not the full HTML.

What to do

  1. In Actor Input, open Proxy configuration and ensure Use Apify Proxy is on (this is the normal fix on Apify Cloud).
  2. If datacenter IPs are still blocked, add the RESIDENTIAL proxy group in the same UI (extra Apify proxy cost).
  3. Locally: run apify login so the SDK can obtain your proxy password; then apify run.
  4. Environment variable (optional): HUBSPOT_RESIDENTIAL_PROXY=1 — when your input proxy block is empty, the Actor forces residential Apify proxy; if you already set groups in input, it respects your input (unless groups are empty and the env flag is set — then it defaults groups to residential).

Advanced (rare): HUBSPOT_BROWSER_COOKIE — paste a Cookie header from a browser session that already passed Cloudflare on app.hubspot.com. Cookies expire quickly and are sensitive; prefer proxy for automation.


Input

FieldRequiredDescription
emailsYesOne email per line (string list). Maximum 10,000 per run.
proxyConfigurationNoStandard Apify proxy editor. Recommended: useApifyProxy: true. Add RESIDENTIAL if Cloudflare keeps blocking.

Output (dataset & stores)

Default dataset — one object per input email (same order as processing):

FieldDescription
emailAddress checked (trimmed).
registeredtrue / false / null — see Understanding your results.
hubspotStatusStatus string from HubSpot JSON when present.
hubspotMessageMessage from HubSpot when present.
correlationIdCorrelation id from HubSpot when present.
httpStatusHTTP status code for that request.
errorShort explanation when the outcome is unclear or the row was skipped (e.g. invalid format).
checkedAtISO-8601 timestamp when the row was produced.

Key-value store — key RUN_LOG: plain text progress line (checked / total emails).

Apify Output tab — after a run, links may include: raw dataset items, results view (?view=results), REST API URL for the run, and RUN_LOG — depending on the Actor’s output_schema.json.


Example inputs

Minimal (Console will still show proxy UI; prefer enabling proxy there)

{
"emails": [
"person@example.com",
"other@company.org"
]
}

Recommended shape (explicit Apify proxy)

{
"emails": [
"person@example.com",
"other@company.org"
],
"proxyConfiguration": {
"useApifyProxy": true
}
}

Stubborn Cloudflare (residential)

{
"emails": ["person@example.com"],
"proxyConfiguration": {
"useApifyProxy": true,
"apifyProxyGroups": ["RESIDENTIAL"],
"apifyProxyCountry": "US"
}
}

Logs during a run

  • Per email: after each address is written to the dataset, an INFO log line summarizes that row (e.g. likely has HubSpot login, likely no, or unclear with a short hint).
  • End of run: one INFO line with counts (how many likely yes / no / unclear / invalid) — useful for quick monitoring without opening the dataset.

The dataset remains the source of truth for full detail; logs are for progress and summary.


Limits

  • 10,000 emails per run (split into multiple runs if you need more).
  • Best-effort mapping — HubSpot may change JSON shapes; the Actor is updated when maintainers notice breakage.
  • Rate limiting — excessive runs may trigger throttling; use reasonable batch sizes and delays (built-in between emails).

Support & contact

Questions or issues? Email Corentin Robert.


Developers: local run, tests, deploy

Local run (recommended over npm start alone)

npm install
apify login # so Apify Proxy can work locally
apify run

Input can live in storage/key_value_stores/default/INPUT.json or project root input.json (merged when not running on the Apify platform). Output appears under storage/ locally and does not sync to the cloud until you run on Apify.

Tests

npm run test:unit # offline — JSON interpretation only
npm run test:smoke # one live request (uses proxy when available)
npm test # both

The smoke test expects a synthetic email to get a “no user” style JSON response. If your network returns 403 + Cloudflare without proxy, the script may skip with a warning (exit 0).

Deploy

$apify push

In .actor/actor.json, bump version as MAJOR.MINOR only (e.g. 1.4, 1.5) when you publish a new build.

Maintainer notes: AGENTS.md.