Unadhi Guides

Turn a website contact scrape into a HubSpot or Pipedrive import file: one company per website, its inboxes linked

Updated 20 Oct 2026 · Disclosure: the contact scraper linked below is an Unadhi product on the Apify Store. This guide is free, and the sheet works with a CSV from any tool or a list you build by hand. Current Apify pricing is only on the Store page. HubSpot and Pipedrive steps follow their own help pages, linked at the end; menus can move, so check there if a button has a new name.

What you get: one CRM import file (a CSV made in Google Sheets or Excel) that HubSpot or Pipedrive can read in one go: one company per website, each public inbox on that company's own domain (info@, sales@, bookings@) as a contact linked to its company, plus the company phone, LinkedIn page, website and the page where each email was found. Emails on another domain, failed sites and addresses that cannot receive mail go to a separate check_first tab instead of your CRM. Setup is about 30 minutes; every later scrape takes two minutes.

The finished import file

Company nameCompany domain nameWebsite URLCompany phoneLinkedIn company pageEmailFound onContact name
example-clinic.inexample-clinic.inhttps://example-clinic.in+914000000001appointments@example-clinic.in…/contact-usAppointments inbox
example-clinic.inexample-clinic.inhttps://example-clinic.in+914000000001info@example-clinic.in…/Info inbox
Example Studioexample-studio.comhttps://example-studio.comlinkedin.com/company/example-studiohello@example-studio.com…/aboutHello inbox

Example rows only, to show the layout. Not real business data.

Two rows with the same domain become one company with two contacts in the CRM. That is what you want: the company record holds the phone and LinkedIn page, and each inbox sits under it.

Why you cannot import the raw scrape directly

Step 1: get one contact CSV

Free, a few businesses

For ten or twenty companies, open each contact page and type what it publishes into a sheet with these column names: startUrl, domain, status (type ok), emails/0/email, emails/0/foundOn, emails/0/sameDomain (TRUE), phones/0/phone. Already have a CSV from another tool? Rename its columns to these names and go to Step 2.

No code, hundreds of websites (Apify)

  1. Create a free Apify account (no card needed for the free plan; see apify.com/pricing for current free monthly usage).
  2. Open Website Contact Scraper: Emails, Phones & WhatsApp and click Try for free.
  3. Paste your websites. In JSON view:
{
  "urls": ["example-clinic.in", "example-studio.com"],
  "maxPagesPerSite": 4,
  "includePersonalEmails": false,
  "checkEmailMx": true,
  "respectRobotsTxt": true,
  "respectTermsOfService": true,
  "defaultCountry": "IN"
}

Keep includePersonalEmails off: a shared role inbox is the right first contact for a company, and it keeps named people's addresses out of your CRM. Keep checkEmailMx on, because Step 4 uses mxValid. Set defaultCountry to where most of the businesses are, so local phone numbers are read correctly. Starting from a Google Maps dataset? Pass its ID in datasetId (see enrich a Google Maps Apify dataset); the business name then arrives as sourceItems/0/title and becomes the company name.

When the run finishes, open the dataset, choose Export → CSV and download it.

Step 2: import it as text into a tab called raw, and add COL

Then add a helper that picks a column by its header name (column order can change between runs). Google Sheets: Data → Named functions → Add new function, name COL, argument h, definition:

=IFERROR(XLOOKUP(h, raw!$1:$1, raw!$2:$5000), "")

Excel 365: Formulas → Name Manager → New, name COL, refers to:

=LAMBDA(h, IFERROR(XLOOKUP(h, raw!$1:$1, raw!$2:$5000), ""))

Already built the call sheet? It uses the same raw tab and COL, so add the tabs below to that file.

Step 3: one tab per email slot (e0 and e1)

Add a tab called e0. Type the headers in row 1 and each formula in row 2. In Excel 365 you can leave out ARRAYFORMULA; the results spill on their own.

ColHeaderFormula in row 2
Acompany=ARRAYFORMULA(IF(COL("sourceItems/0/title")<>"", COL("sourceItems/0/title"), COL("domain")))
Bdomain=COL("domain")
Cwebsite=COL("startUrl")
Dphonesee below
Elinkedin=COL("socials/linkedin/0/url")
Femail=COL("emails/0/email")
Gfound on=COL("emails/0/foundOn")
Hstatus=COL("status")
Imx=ARRAYFORMULA(UPPER(COL("emails/0/mxValid")&""))
Jsame domain=ARRAYFORMULA(UPPER(COL("emails/0/sameDomain")&""))

D: company phone (a clickable tel: link first, otherwise the first number)

=ARRAYFORMULA(IF(COL("phones/0/source")="tel-link", COL("phones/0/phone"),
  IF(COL("phones/1/source")="tel-link", COL("phones/1/phone"), COL("phones/0/phone"))))

Now duplicate the tab, rename the copy e1, and change emails/0/ to emails/1/ in columns F, G, I and J. That picks up each site's second inbox. Sites often publish more; repeat with e2 and emails/2/ if your scrape has those columns.

UPPER(…&"") makes the true/false columns read the same whether your sheet imported them as text or as TRUE/FALSE. If a column does not exist in this run (say no site had a second email), COL returns a blank and the tab simply stays empty.

Step 4: the crm_import tab (stack, check, de-duplicate)

Add a tab called crm_import. Type these headers in row 1, A to H: Company name, Company domain name, Website URL, Company phone, LinkedIn company page, Email, Found on, Contact name. In A2:

=ARRAYFORMULA(LET(all, VSTACK(e0!A2:J5000, e1!A2:J5000),
  keep, (CHOOSECOLS(all,6)<>"") * (CHOOSECOLS(all,8)="ok")
      * (CHOOSECOLS(all,9)<>"FALSE") * (CHOOSECOLS(all,10)="TRUE"),
  UNIQUE(CHOOSECOLS(FILTER(all, keep), 1, 2, 3, 4, 5, 6, 7))))

It keeps a row only when there is an email, the site was read normally, the email's domain can receive mail (blank counts as "not checked" and is kept), and the email is on the company's own domain. UNIQUE drops exact repeats, for example when you merged two runs. Added an e2 tab? Add e2!A2:J5000 inside VSTACK.

In H2, give each inbox a plain contact name (Pipedrive needs a name for every person):

=ARRAYFORMULA(IF(F2:F="", "", PROPER(LEFT(F2:F, FIND("@", F2:F) - 1)) & " inbox"))

That turns sales@example.com into "Sales inbox". It says what the contact really is: a shared company mailbox, not a named person. When you later learn who reads it, rename the contact in the CRM.

Last check: in any empty cell, =ROWS(F2:F) - COUNTBLANK(F2:F) - COUNTUNIQUE(F2:F) (Excel: =ROWS(A2#) - ROWS(UNIQUE(CHOOSECOLS(A2#, 6)))) should be 0. Anything else means one email appears under two companies; look it up and keep the right row.

The check_first tab

Everything left out of the import, with the reason visible in columns H to J:

=ARRAYFORMULA(LET(all, VSTACK(e0!A2:J5000, e1!A2:J5000),
  FILTER(all, (CHOOSECOLS(all,6)<>"") * ((CHOOSECOLS(all,8)<>"ok")
    + (CHOOSECOLS(all,9)="FALSE") + (CHOOSECOLS(all,10)<>"TRUE")))))

Open the "found on" page for each one. An email on another domain can be the right address (some firms use a group domain or a free mailbox), or it can be an agency's. Add it by hand only once you are sure.

Step 5: download the CSV

Step 6a: import into HubSpot (contacts and companies, one file)

  1. Go to Data Management → Data Integration (or click Import on the Contacts page), then Import data → Advanced imports (all objects).
  2. Select Contacts and Companies, then Single file. For each, choose Create and update.
  3. Upload the CSV and map the columns:
Your columnHubSpot objectHubSpot property
EmailContactEmail (unique identifier, key icon)
Company domain nameCompanyCompany domain name (unique identifier)
Company nameCompanyCompany name
Website URLCompanyWebsite URL
Company phoneCompanyPhone number
LinkedIn company pageCompanyLinkedIn company page
Contact nameContactFirst name
Found onContacta single-line text property you create first (for example "Found on"), or don't import

HubSpot needs Email to create a contact and Name or Company domain name to create a company. Using Email and Company domain name as identifiers means a second import updates the same records instead of creating duplicates. Rows that share a domain become one company with several contacts. Company domain name only keeps the part up to the top-level domain, which is why the file uses the bare domain column, not the full URL.

If the import asks whether to set the new contacts as marketing contacts, leave that off unless you have a lawful basis to send them marketing email.

Step 6b: import into Pipedrive (people and organizations)

  1. Pipedrive accepts CSV, XLS or XLSX with a header row (one tab per import, up to 200,000 rows and 50 MB). Start an import from a spreadsheet and, at the File info step, select People and Organizations as the data types.
  2. Map Contact name → Person name, Email → Person email, Company name → Organization name. Map the phone, website and LinkedIn columns to matching fields, or create custom fields first under Personal preferences → Data fields.
  3. Every person needs a name and every organization needs a name; rows without them land in the skip file. People and the organization in the same row are linked.

If you let Pipedrive merge duplicates, it matches people by name and email, and organizations by name and address. Because the file has no address, two different companies that share a name (two "City Dental" clinics) could merge; when that happens, use the domain as the organization name for one of them.

Other CRMs with a CSV import, such as Zoho CRM, work the same way: map Company name to the account or company, Email to the contact, and use the domain as the de-duplication key if the CRM offers one.

What not to do

This guide is general information, not legal advice. You are responsible for how you use the data and for following each site's terms and your local law. The Apify Actor mentioned reads only public pages, uses an honest bot User-Agent, follows robots.txt, never logs in and never gets around blocks.

Partner programme opening soon

Partner programme opening soon: join the free waitlist. Planned terms are 50% of each referred sale (75% once you have 5+ paying customers), single level, paid through Gumroad only from revenue received.

Sources

Related

← All guides

Unadhi Guides are free, independent explainers. We correct errors as soon as we find them: write to mininglife7@gmail.com.