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.
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#
- Go to Contacts → Contacts in HubSpot
- Click Actions (top right) → Export
- Select all properties you want (click "Select all" to get everything)
- Choose CSV format
- 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#
- Go to Companies → Companies
- Actions → Export
- Select all properties
- CSV format, click Export
Export Deals#
- Go to Deals → Deals
- Actions → Export
- 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:
- Go to Reports → Analytics Tools → Activities
- Or use Data Management → Export to run a full export
For a full data export including all historical data:
- Go to Settings → Data Management → Export All Data
- 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 File | DenchClaw Object |
|---|---|
| contacts.csv | people |
| companies.csv | companies |
| deals.csv | deals |
| notes.csv | documents (linked to entries) |
| calls.csv | activities |
| emails.csv | activities |
| meetings.csv | activities |
Step 3: Field Mapping — HubSpot to DenchClaw#
Contacts → People#
| HubSpot Property | DenchClaw Field | Notes |
|---|---|---|
| First Name | first_name | |
| Last Name | last_name | |
| Primary dedup key | ||
| Phone Number | phone | |
| Company Name | company_name | |
| Job Title | job_title | |
| Lifecycle Stage | status | Map stages (see below) |
| Lead Status | lead_status | |
| HubSpot Owner | owner | Import as text |
| Create Date | created_at | |
| Last Activity Date | last_activity | |
| City | city | |
| State/Region | state | |
| Country/Region | country | |
| LinkedIn URL | linkedin_url | |
| Website URL | website |
Lifecycle Stage mapping:
| HubSpot Lifecycle Stage | DenchClaw Status |
|---|---|
| Subscriber | Subscriber |
| Lead | Lead |
| Marketing Qualified Lead | MQL |
| Sales Qualified Lead | SQL |
| Opportunity | Opportunity |
| Customer | Customer |
| Evangelist | Customer |
| Other | Other |
Deals → Deals#
| HubSpot Property | DenchClaw Field | Notes |
|---|---|---|
| Deal Name | name | |
| Amount | value | |
| Deal Stage | status | Map stages (see below) |
| Close Date | close_date | |
| Pipeline | pipeline | If using multiple pipelines |
| HubSpot Owner | owner | |
| Create Date | created_at | |
| Days to Close | computed | Calculate on import |
| Associated Contact | contact (relation) | Post-import |
| Associated Company | company (relation) | Post-import |
Deal Stage mapping (default HubSpot pipeline):
| HubSpot Stage | DenchClaw Status |
|---|---|
| Appointment Scheduled | Qualified |
| Qualified to Buy | Qualified |
| Presentation Scheduled | Proposal |
| Decision Maker Bought-In | Proposal |
| Contract Sent | Negotiation |
| Closed Won | Closed Won |
| Closed Lost | Closed 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/*.csvClean 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 500Import 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 nameImport 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 nameVerify 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:
-
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). -
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.
-
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.
-
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 Size | Time |
|---|---|
| < 1,000 contacts, simple pipeline | 4-6 hours |
| 1,000-5,000 contacts, 1-2 pipelines | 1 day |
| 5,000-20,000 contacts, complex setup | 2-3 days |
| Large portal with sequences, custom objects | 3-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 →
