Back to The Times of Claw

The Complete HubSpot to DenchClaw Migration Guide

Complete HubSpot to DenchClaw migration guide: export contacts, deals, companies, map fields, import to DuckDB, recreate pipelines, and cut your CRM costs to zero.

Mark Rachapoom
Mark Rachapoom
·10 min read
The Complete HubSpot to DenchClaw Migration Guide

The Complete HubSpot to DenchClaw Migration Guide

HubSpot starts free and ends expensive. Once you need custom properties, sequences, reporting, or more than 1,000 contacts without ads, you're looking at Starter ($20/user/month), Professional ($890/month for 3 users), or Enterprise ($3,600/month). That's real money for a small team.

DenchClaw is free, open source (MIT), runs locally on your machine, and has AI built in. This guide walks you through every step of moving from HubSpot to DenchClaw: exporting your data, mapping fields, importing into DuckDB, recreating your pipeline, and handling the edge cases. Budget 1-3 days depending on your HubSpot data complexity.

Why Leave HubSpot#

Let's be direct about the tradeoffs.

The cost problem: HubSpot Professional for a 3-person team costs ~$890/month ($10,680/year). That pays for a lot of other tools. If you're a startup or small team, that's significant budget.

The data ownership problem: Your CRM data lives on HubSpot's servers. If HubSpot goes down, changes pricing, or gets acquired, you're dependent on their export tools to get your data back. With DenchClaw, your data is a DuckDB file on your own machine.

What you gain with DenchClaw:

  • Zero cost (MIT open source)
  • Full data ownership
  • Natural language queries ("who are my top 10 leads this quarter?") via Telegram/Discord
  • DuckDB backend — run arbitrary SQL, build custom reports
  • Browser agent that works with your existing logged-in sessions

What HubSpot does better:

  • Email tracking (open/click notifications)
  • Sequences (automated follow-up emails)
  • Meeting scheduling integration
  • Built-in reporting and dashboards
  • Marketing hub (landing pages, forms, ads)

If email sequences and marketing automation are core to your workflow, plan workarounds before migrating. For pure CRM use (contacts, deals, activities, pipeline), DenchClaw covers everything.

Step 1: Export All HubSpot Data#

HubSpot's export tools are thorough. Here's what to export and where to find each export.

Export Contacts#

  1. Go to ContactsContacts in HubSpot
  2. Click Actions (top right) → Export
  3. Select all properties you want (click "Select all" to get everything)
  4. Choose CSV format
  5. Click Export — HubSpot emails you a download link

The export includes: first name, last name, email, phone, company, job title, lifecycle stage, lead status, owner, create date, last activity date, and all custom properties.

Export Companies#

  1. Go to CompaniesCompanies
  2. ActionsExport
  3. Select all properties
  4. CSV format, click Export

Export Deals#

  1. Go to DealsDeals
  2. ActionsExport
  3. Include: deal name, amount, stage, close date, associated contact, associated company, owner, create date, all custom properties

Export Activities (Notes, Calls, Emails)#

Activities are the trickiest export. In HubSpot:

  1. Go to ReportsAnalytics ToolsActivities
  2. Or use Data ManagementExport to run a full export

For a full data export including all historical data:

  1. Go to SettingsData ManagementExport All Data
  2. This queues a full export of your entire HubSpot portal — all objects, properties, and associations

The full export gives you a zip file with separate CSVs for each object type.

Step 2: Understand the HubSpot Data Structure#

HubSpot exports come as separate CSVs. Here's how they map:

HubSpot CSV FileDenchClaw Object
contacts.csvpeople
companies.csvcompanies
deals.csvdeals
notes.csvdocuments (linked to entries)
calls.csvactivities
emails.csvactivities
meetings.csvactivities

Step 3: Field Mapping — HubSpot to DenchClaw#

Contacts → People#

HubSpot PropertyDenchClaw FieldNotes
First Namefirst_name
Last Namelast_name
EmailemailPrimary dedup key
Phone Numberphone
Company Namecompany_name
Job Titlejob_title
Lifecycle StagestatusMap stages (see below)
Lead Statuslead_status
HubSpot OwnerownerImport as text
Create Datecreated_at
Last Activity Datelast_activity
Citycity
State/Regionstate
Country/Regioncountry
LinkedIn URLlinkedin_url
Website URLwebsite

Lifecycle Stage mapping:

HubSpot Lifecycle StageDenchClaw Status
SubscriberSubscriber
LeadLead
Marketing Qualified LeadMQL
Sales Qualified LeadSQL
OpportunityOpportunity
CustomerCustomer
EvangelistCustomer
OtherOther

Deals → Deals#

HubSpot PropertyDenchClaw FieldNotes
Deal Namename
Amountvalue
Deal StagestatusMap stages (see below)
Close Dateclose_date
PipelinepipelineIf using multiple pipelines
HubSpot Ownerowner
Create Datecreated_at
Days to ClosecomputedCalculate on import
Associated Contactcontact (relation)Post-import
Associated Companycompany (relation)Post-import

Deal Stage mapping (default HubSpot pipeline):

HubSpot StageDenchClaw Status
Appointment ScheduledQualified
Qualified to BuyQualified
Presentation ScheduledProposal
Decision Maker Bought-InProposal
Contract SentNegotiation
Closed WonClosed Won
Closed LostClosed Lost

Step 4: Prepare Your CSV Files for Import#

# Check your exports landed correctly
ls -la hubspot-export/
# contacts.csv  companies.csv  deals.csv  notes.csv
 
# Preview contacts
head -3 hubspot-export/contacts.csv
 
# Count rows
wc -l hubspot-export/*.csv

Clean common HubSpot CSV issues:

import pandas as pd
import numpy as np
 
# Load HubSpot contacts export
df = pd.read_csv('hubspot-export/contacts.csv')
 
# Combine first + last name
df['name'] = df['First Name'].fillna('') + ' ' + df['Last Name'].fillna('')
df['name'] = df['name'].str.strip()
 
# Normalize phone numbers (remove HubSpot formatting)
df['phone'] = df['Phone Number'].str.replace(r'[^\d+]', '', regex=True)
 
# Map lifecycle stages
stage_map = {
    'lead': 'Lead',
    'marketingqualifiedlead': 'MQL', 
    'salesqualifiedlead': 'SQL',
    'opportunity': 'Opportunity',
    'customer': 'Customer',
    'subscriber': 'Subscriber'
}
df['status'] = df['Lifecycle Stage'].str.lower().str.replace(' ', '').map(stage_map)
 
# Select and rename columns for DenchClaw
output = df[[
    'name', 'Email', 'phone', 'Company Name', 'Job Title',
    'status', 'Create Date'
]].rename(columns={
    'Email': 'email',
    'Company Name': 'company_name',
    'Job Title': 'job_title',
    'Create Date': 'created_at'
})
 
output.to_csv('contacts_ready.csv', index=False)
print(f"Prepared {len(output)} contacts")

Step 5: Import Into DuckDB#

Import contacts#

npx denchclaw import csv \
  --file contacts_ready.csv \
  --object people \
  --dedupe email \
  --batch-size 500

Import companies#

npx denchclaw import csv \
  --file hubspot-export/companies.csv \
  --object companies \
  --field-map \
    "Company Name:name" \
    "Website URL:website" \
    "Phone Number:phone" \
    "City:city" \
    "State/Region:state" \
    "Country/Region:country" \
    "Industry:industry" \
    "Annual Revenue:annual_revenue" \
    "Number of Employees:employees" \
  --dedupe name

Import deals#

npx denchclaw import csv \
  --file hubspot-export/deals.csv \
  --object deals \
  --field-map \
    "Deal Name:name" \
    "Amount:value" \
    "Deal Stage:status" \
    "Close Date:close_date" \
    "Create Date:created_at" \
  --dedupe name

Verify imports with DuckDB#

-- Counts
SELECT 'people' as object, COUNT(*) as count FROM v_people
UNION ALL SELECT 'companies', COUNT(*) FROM v_companies
UNION ALL SELECT 'deals', COUNT(*) FROM v_deals;
 
-- Check for null emails (common data quality issue)
SELECT COUNT(*) as missing_email FROM v_people WHERE email IS NULL;
 
-- Deal value distribution
SELECT 
  status,
  COUNT(*) as count,
  SUM(value::DECIMAL) as total_value
FROM v_deals
GROUP BY status
ORDER BY total_value DESC;

Step 6: Recreate HubSpot Pipelines as Kanban Views#

HubSpot's deal pipeline is a kanban board. DenchClaw has the same.

Create the pipeline view#

npx denchclaw view create \
  --object deals \
  --name "Sales Pipeline" \
  --type kanban \
  --group-by status \
  --stages "Lead,Qualified,Proposal,Negotiation,Closed Won,Closed Lost"

Add a revenue summary#

-- Query to see pipeline value by stage (ask DenchClaw this in natural language)
SELECT 
  status as stage,
  COUNT(*) as deals,
  SUM(value::DECIMAL) as total_value,
  AVG(value::DECIMAL) as avg_value
FROM v_deals
WHERE status NOT IN ('Closed Won', 'Closed Lost')
GROUP BY status
ORDER BY total_value DESC;

Step 7: Migrate Custom Properties to DenchClaw Fields#

HubSpot custom properties become custom fields in DenchClaw.

List your custom properties#

In HubSpot: Settings → Data Management → Properties → Filter by "Custom Properties"

Create matching fields in DenchClaw#

# Create each custom field
npx denchclaw field create --object people --name "lead_score" --type number
npx denchclaw field create --object people --name "utm_source" --type text
npx denchclaw field create --object people --name "product_interest" --type select \
  --options "Product A,Product B,Product C"
npx denchclaw field create --object deals --name "competitor" --type text
npx denchclaw field create --object deals --name "reason_lost" --type select \
  --options "Price,Features,Timing,Competitor,No decision"

Step 8: Email Sequence Migration#

This is the part where HubSpot has a genuine advantage. Email sequences (automated drip campaigns) don't have a direct DenchClaw equivalent.

Workarounds:

  1. Export active sequence enrollments: In HubSpot, export the list of contacts actively in sequences and their current step. Import this as a field in DenchClaw (sequence_step, sequence_name).

  2. Use DenchClaw's webhook + Postmark/SendGrid: Set up outgoing webhooks in DenchClaw that trigger email sends via an email API when a contact reaches certain stages.

  3. External email tools: Tools like Customer.io, Loops.so, or even Mailchimp can handle sequences. Use DenchClaw webhooks to add/remove contacts from these tools based on CRM events.

  4. Simple follow-up reminders: For manual follow-up sequences, use DenchClaw's task/reminder system instead of automated emails.

Step 9: Import Notes and Activities#

HubSpot notes export as separate CSV files. Import them as DenchClaw documents linked to entries.

# Import notes
npx denchclaw import notes \
  --file hubspot-export/notes.csv \
  --contact-field "Associated Contact"

Or via DuckDB directly for bulk import:

import pandas as pd
import subprocess
import json
 
notes = pd.read_csv('hubspot-export/notes.csv')
 
for _, note in notes.iterrows():
    if pd.notna(note.get('Note Body')) and pd.notna(note.get('Associated Contact')):
        cmd = [
            'npx', 'denchclaw', 'note', 'create',
            '--contact-email', str(note['Associated Contact']),
            '--content', str(note['Note Body']),
            '--date', str(note.get('Create Date', ''))
        ]
        subprocess.run(cmd, capture_output=True)
 
print("Notes imported")

Migration Timeline (Realistic)#

HubSpot SizeTime
< 1,000 contacts, simple pipeline4-6 hours
1,000-5,000 contacts, 1-2 pipelines1 day
5,000-20,000 contacts, complex setup2-3 days
Large portal with sequences, custom objects3-5 days

Day 1: Export everything, clean contacts and deals CSVs, import to DenchClaw, verify counts. Day 2: Recreate pipeline views, import notes, set up key custom fields, test core workflows. Day 3 (if needed): Handle edge cases, import activities, set up webhooks for sequence replacements.

FAQ#

Will I lose my HubSpot email open/click tracking history? Yes. Email engagement data (opens, clicks) lives in HubSpot and doesn't export cleanly. The contacts and deal history come over, but email analytics don't.

Can I import HubSpot lists and segments? Not directly. Recreate important lists as DenchClaw saved views with the equivalent filter criteria.

What about HubSpot forms embedded on my website? Replace them with DenchClaw incoming webhooks. Most form tools (Typeform, Tally, JotForm) support webhook submission. Point the webhook at DenchClaw instead of HubSpot.

How do I handle HubSpot's "Associated Contact" on deals? Import deals first, then run a post-import SQL update to link deals to people by matching the contact name/email field. The DenchClaw import guide has the SQL pattern for this.

Can I run HubSpot and DenchClaw in parallel? Yes. Keep HubSpot active while you validate the DenchClaw migration. Once you're confident, update your forms and integrations to point to DenchClaw, then cancel HubSpot.

Ready to try DenchClaw? Install in one command: npx denchclaw. Full setup guide →

Mark Rachapoom

Written by

Mark Rachapoom

Building the future of AI CRM software.

Continue reading

DENCH

© 2026 DenchHQ · San Francisco, CA