How to Export Your HubSpot CMS Content Without Losing Anything
A step-by-step guide to exporting every piece of content from HubSpot CMS — blog posts, pages, HubDB, forms, files, and metadata — without missing anything.
MigrateLab Team
Migration Experts

HubSpot CMS Content Is Exportable — With the Right Approach
One of the biggest fears about leaving HubSpot CMS is losing content. Will your blog posts survive the transition? What about your carefully crafted landing pages, HubDB tables, and file assets? The good news: everything is exportable. HubSpot provides APIs for every content type, and the export process is systematic and repeatable.
The bad news: there's no single 'Export Everything' button. You need to use multiple APIs, export tools, and manual processes to capture everything. Different content types live in different parts of HubSpot and require different extraction approaches. This guide covers every content type and the best method to export each one.
Before You Start: Content Audit
Before exporting anything, audit your HubSpot CMS content to know exactly what you're working with:
- Count your content types. Log into HubSpot and check: how many website pages? How many landing pages? How many blog posts? How many HubDB tables? How many files in File Manager? These numbers determine the complexity and timeline of your export.
- Identify what's actively used. HubSpot accumulates draft pages, test landing pages, and unused templates over time. Not everything needs to migrate. Mark content as 'migrate,' 'redirect-only,' or 'discard.' This reduces migration scope and prevents dead content from cluttering your new site.
- Document your URL structure. Export your full URL list from Settings > Website > Pages. This becomes your redirect map. Every published URL needs to either exist on the new site or redirect to the appropriate new URL.
- Catalog your forms and CTAs. List every HubSpot form and CTA used on the site. Note which forms are embedded on which pages, what fields they collect, and which workflows they trigger. This information is critical for maintaining CRM data flow after migration.
- Check your API access. You'll need a HubSpot private app with CMS scopes. Go to Settings > Integrations > Private Apps > Create a private app. Grant it read access to CMS content, HubDB, Files, and Blog APIs. Copy the access token — you'll use it for all API calls.
Exporting Blog Posts
Blog posts are typically the largest content set in a HubSpot CMS migration. HubSpot provides two export methods:
Method 1: Blog API (Recommended)
The Blog Posts API (GET /cms/v3/blogs/posts) returns structured JSON with all the data you need: title, slug, body HTML, meta description, featured image URL, author, tags, publish date, and more. Each response returns up to 100 posts with pagination via the after cursor parameter.
Here's what the API returns for each post:
- name: the post title
- slug: the URL slug (e.g., 'complete-migration-guide')
- postBody: the full HTML body content
- metaDescription: the SEO meta description
- featuredImage: URL to the featured image
- blogAuthor: author object with name and other details
- tagIds: array of tag IDs (fetch tag names separately via /blogs/tags)
- publishDate: ISO timestamp of publication
- htmlTitle: the SEO title (may differ from the post title)
- canonicalUrl: canonical URL if set
Write a script that paginates through all posts, fetches associated tags, and saves the result as JSON. This JSON becomes the source of truth for your blog content migration.
Method 2: CSV Export (Quick but Limited)
HubSpot offers a CSV export from Marketing > Blog > Actions > Export. This gives you post titles, URLs, publish dates, and authors in spreadsheet format. But it doesn't include the full body content, meta descriptions, or featured image URLs. Use the CSV export as a verification checklist (to confirm you have every post), not as your primary export method.
Exporting Website Pages and Landing Pages
Website pages and landing pages are separate content types in HubSpot, each with their own API endpoint:
- Website pages: GET /cms/v3/pages/site-pages
- Landing pages: GET /cms/v3/pages/landing-pages
Both endpoints return similar data: page title, slug, body content (as HTML), meta description, featured image, template path, and widget data. The key field is layoutSections — this contains the structured content for pages built with HubSpot's drag-and-drop editor. Each section contains columns, rows, and modules with their field values.
For pages built with the drag-and-drop editor, the content isn't in a single HTML body field. It's distributed across layoutSections objects that describe the page structure. You'll need to traverse this structure, extract the content from each module, and convert it to your new CMS's content format. This is more complex than blog post export but follows a predictable structure.
For pages built with coded templates (HubL files), the content is stored in widgetContainers and widgets objects within the page response. Each widget corresponds to a HubL {% module %} tag in the template, with field values matching the module's field definition.
Exporting HubDB Tables
HubDB tables contain structured data used for dynamic pages (team directories, location listings, product catalogs, etc.). Export each table using the HubDB API:
- List all tables: GET /cms/v3/hubdb/tables. Returns table IDs, names, and column definitions.
- Fetch table rows: GET /cms/v3/hubdb/tables/{tableId}/rows. Returns all rows with column values. Paginated at 100 rows per request.
- Export column definitions: The table response includes column metadata (name, type, options for select columns). Save these — they define your new CMS collection schema.
HubDB supports several column types: text, number, date, datetime, select, multi-select, boolean, URL, image, and foreign table (relationship). Map each type to the equivalent field type in your new CMS. Most mappings are straightforward, but foreign table columns (references to rows in other HubDB tables) need to be converted to relationship fields in your new CMS.
Exporting Forms and CTAs
HubSpot forms don't need traditional 'exporting' because you'll likely continue using HubSpot forms after migration (they work on any website). But you should document them:
- Form inventory: GET /marketing/v3/forms returns all forms with field definitions, redirect URLs, and notification settings.
- Form-to-page mapping: Document which forms appear on which pages. This ensures you embed the correct form on each migrated page.
- CTA inventory: HubSpot CTAs are more HubSpot-specific. If you use embedded CTAs, note their text, link targets, and which pages they appear on. In most migrations, CTAs become React button components rather than embedded HubSpot CTAs.
If you want to rebuild forms as custom React components (for full design control), export the form field definitions from the API. Each form has a fieldGroups array containing field objects with name, type, required status, validation rules, and options for select fields. These definitions are your blueprint for building equivalent React forms that submit to the HubSpot Forms API.
Exporting File Manager Assets
The HubSpot File Manager stores images, PDFs, videos, and other assets used on your site. Export them using the Files API:
- List all files: GET /filemanager/api/v3/files/search returns file metadata including URLs, sizes, and folder paths.
- Download files: Each file has a public URL. Write a script that downloads all files, preserving the folder structure. Store the old-URL-to-new-URL mapping for content reference updates.
- Focus on referenced files: The File Manager often contains old, unused files. Instead of downloading everything, cross-reference your file list with the image URLs found in your page and blog content. Only migrate files that are actually used.
Rate limit note: the Files API has the same rate limits as other HubSpot APIs (100 requests per 10 seconds). For large file collections, build in delays between download requests. Consider running the download overnight for sites with 1,000+ assets.
Exporting HubL Templates and Modules
Your HubL templates can't run outside HubSpot, but they're valuable as a reference during migration. Use the HubSpot CLI to download them:
- Install the HubSpot CLI: npm install -g @hubspot/cli
- Authenticate: hs init (follow the prompts to connect your HubSpot portal)
- Download Design Manager files: hs fetch --overwrite downloads all templates, modules, CSS, and JavaScript to your local machine
The downloaded files include:
- .html files: HubL templates with layout structure, module references, and conditional logic
- modules/ directories: Each custom module has a module.html (template), fields.json (field definitions), and meta.json (metadata)
- .css and .js files: Stylesheets and scripts used by your templates
Use these files as reference when building React components. The fields.json file in each module is particularly valuable — it contains the exact field structure (types, labels, default values, help text) that you'll need to replicate in your new CMS block definitions.
Preserving Metadata That Matters
Beyond content, HubSpot stores metadata that must survive the migration:
- SEO titles (htmlTitle): Different from the page title. Export this separately and map it to your new CMS's SEO title field.
- Meta descriptions (metaDescription): These influence click-through rates from search results. Preserve them exactly.
- Canonical URLs: If any pages have custom canonical URLs set, export and preserve them.
- Open Graph data: OG title, description, and image. Some HubSpot pages have custom OG settings that differ from the page's primary meta.
- Publish dates: For blog posts, the original publish date affects SEO freshness signals. Use the original publishDate from the API, not the migration date.
- Author data: Blog author names, bios, and avatars. Export from /blogs/authors endpoint.
Handling Embedded HubSpot Elements in Migrated Content
HubSpot content often contains embedded elements that need special handling:
Embedded Forms
HubSpot forms embedded in blog posts or page content appear as JavaScript embed codes. During migration, you have two options: preserve the HubSpot embed code in your content (it works on any website), or replace it with your custom React form component. For most migrations, keeping the HubSpot embed is simpler and maintains workflow triggers.
Embedded CTAs
HubSpot CTA embeds are proprietary and won't work outside HubSpot. Find-and-replace CTA embed codes in your content with your own button components that link to the same target URLs. Regex patterns for HubSpot CTA embeds: look for scripts containing 'cta_redirect_element' or 'hs-cta-wrapper' div elements.
Embedded Videos
HubSpot Video embeds use HubSpot's video hosting. If you've used HubSpot Video for content, these embed codes will stop working when you leave the CMS. Re-host videos on YouTube, Vimeo, or a CDN and update the embed codes. Standard YouTube/Vimeo embeds in your content work fine and need no changes.
Smart Content Blocks
Smart content that shows different content based on CRM data is HubSpot-specific. During export, you get the default version of the content. Document which pages use smart content and decide: migrate the default content only (simplest), or rebuild the personalization logic on your new platform (more work, preserves the feature).
Verification: Ensuring Nothing Was Lost
After export, verify completeness:
- Compare page count: number of exported pages should match HubSpot's published page count
- Compare blog post count: number of exported posts should match HubSpot's published post count
- Spot-check 10 random blog posts: body content, featured image, meta description, tags all present
- Spot-check 5 random pages: content sections, images, forms all captured
- Verify all HubDB tables exported with correct row counts
- Confirm all referenced images are downloaded and accessible
- Verify author data is complete for all blog authors
- Check that forms inventory matches forms referenced in page content
A thorough export is the foundation of a successful migration. Spend the extra time to verify before moving to the transformation and import phase. Discovering missing content after you've built the new site is expensive and demoralizing. Discovering it during export costs nothing but a few extra minutes.
The 5-Step HubSpot CMS Content Export Process
Set up API access and audit your content
Create a HubSpot private app with CMS read scopes. Count all content types (pages, posts, HubDB tables, files). Mark content as migrate, redirect-only, or discard. Export your URL list from HubSpot settings.
Tip: Create the private app with read-only scopes only. You don't need write access for export, and limiting permissions is good security practice.
Export blog posts and pages via API
Write paginated scripts to fetch all blog posts (/cms/v3/blogs/posts), website pages (/cms/v3/pages/site-pages), and landing pages (/cms/v3/pages/landing-pages). Save raw JSON responses. Fetch blog tags and authors separately.
Tip: Save raw API responses before transforming. If you need to re-run the transformation later, you won't need to re-fetch from HubSpot.
Export HubDB tables and File Manager assets
Export all HubDB tables with column definitions and row data. Download referenced files from File Manager. Map old file URLs to new storage locations for content reference updates during import.
Tip: Only download files that are actually referenced in your content. Cross-reference file URLs found in page/post HTML with File Manager contents to skip orphaned files.
Download Design Manager templates for reference
Use the HubSpot CLI (hs fetch) to download all templates, custom modules, and associated CSS/JS. The fields.json files in each module directory are especially valuable — they define the exact content schema you need to replicate.
Tip: Don't try to convert HubL to React automatically. Use the templates as visual reference and the fields.json as schema reference, then build React components fresh.
Verify export completeness
Compare exported content counts against HubSpot's published content counts. Spot-check random items across all content types. Verify metadata (SEO titles, descriptions, canonical URLs) is captured. Confirm all form references are documented.
Tip: Create a verification spreadsheet: content type, expected count, exported count, spot-check pass/fail. Don't proceed to import until every row shows a pass.
HubSpot API Rate Limits: HubSpot allows 100 API requests per 10 seconds for most endpoints. For large content exports, add 150ms delays between requests. If you hit rate limits, the API returns a 429 status with a Retry-After header. Plan overnight runs for sites with 1,000+ pages or large file collections.
Ready to break free from HubSpot CMS? We handle the technical migration — content, CRM integration, redirects — so you keep what works and lose what holds you back.
Related Resources

HubSpot CMS to Next.js: The Complete Migration Guide for 2026
HubSpot CMS is powerful but expensive and limiting. Here's the complete playbook for migrating to Next.js — from HubL templates to React, CRM integration, content export, and SEO preservation.

HubSpot CMS Migration Cost Breakdown: What to Budget for 2026
HubSpot CMS costs $400-1,200/month. Here's what it actually costs to migrate away, what you'll save, and how fast the investment pays for itself.

The SEO Migration Survival Guide: Keep Your Rankings When Switching Platforms
Platform migrations destroy SEO rankings if done wrong. Here's the checklist we use on every migration to protect (and improve) organic traffic.

Hiring a Developer to Migrate Your HubSpot Site: What to Expect
Decided to leave HubSpot CMS? Here's how to find the right migration partner, what to ask, what to expect, and how to protect your CRM integration during the transition.