While it has long been a go-to option for teams adopting headless CMS architectures, many organizations have now decided to migrate Contentful to Sanity or other setups.
Limits on content types, rigid field definitions, and the absence of a real pay-as-you-go model often make it difficult to stay flexible without moving into costly enterprise plans.
For teams focused on speed, content variety, and developer experience, these constraints are a major bottleneck. This is why they choose a shift toward more customizable and scalable alternatives like Sanity.
In this guide, I’ll show you two easy ways of migrating your setup from Contentful to Sanity. It’s the same SEO-safe migration techniques we use in our projects. Before we start, I’d like to discuss why businesses decide to move from Contentful.
Why Teams Migrate from Contentful to Sanity
Contentful Limitations
Contentful’s Starter and Lite plans are enough for most small-scale projects. However, once content structures start to grow, so do the constraints. The 25-content-type limit can be a serious obstacle for mid-sized or content-heavy applications. There’s no pay-as-you-go option, so scaling up means jumping to a much higher plan instead of paying for incremental usage. Even then, the 50-content-type limit might not be enough in some cases.
On the development side, content models are bound by predefined field types, fixed validations, and a uniform UI that can’t be customized for specific workflows. Rich text editing is also rigid. You can remove formatting options from the toolbar, but not extend or tailor the editor to support things like custom blocks, lists, or reference elements.
Why Sanity Is a Better Fit
Sanity addresses these pain points with a developer-first approach. Its schema system offers full control over content types, relationships, and validation rules. PortableText replaces Contentful’s static rich text editor with a flexible structure that supports custom components and dynamic content.
Real-time collaboration, customizable editing interfaces, and an API built around GROQ queries make it easier to build, query, and scale complex data models. Combined with a more accommodating pricing structure and strong integration with frameworks like Next.js, Sanity offers the agility that growing teams need without forcing trade-offs.
We recommend Sanity because it gives both developers and content teams real freedom. You can shape the CMS around your product, not the other way around.
When comparing costs, Sanity stands out for its gradual, transparent pricing. It includes a forever-free tier and paid plans starting at around $15 per user/month for the “Growth” tier.
Sanity pricing as of October 2025
Contentful does offer a free plan as well, but as soon as you require any meaningful team collaboration or commercial usage, the first paid tier jumps to around $300/month (or higher) for the next level up. Additionally, if you cross 25 content types or have more than 10k of data, you might have to buy the Lite Space, which costs $850.
Contentful pricing as of October 2025
That sharp leap between the free plan and the next level means that the decision to “go live” with Contentful comes with a significant budget step that doesn’t scale gently. Sanity allows a smoother transition from free to paid, whereas with Contentful, you may face a big budget move early on.
Understanding the reasons to migrate Contentful to Sanity, we can look into how to make your transition safe and effective.
GPnotebook
Migrating a 100K+ Page Medical Platform with Next.js & Sanity
Migrating from Contentful to Sanity is a structural change that can impact how your content, SEO, and integrations behave. Before running any scripts, decide which migration strategy makes the most sense for your project and learn about its risks.
Understand the Risks
One of the first challenges is feature parity. Sanity may not have direct replacements for every Contentful plugin, so some marketplace extensions might need to be rebuilt or replaced with custom solutions. In many cases, this becomes an opportunity to clean up unused or outdated features. If a plugin supports a critical part of your workflow, plan for a rebuild.
Next, consider the SEO and content integrity risks. Losing URL structures, internal links, or metadata during transfer can cause ranking drops and broken pages. Redirects, sitemaps, and structured data should be verified early in the process for a smooth transition.
There’s always the risk of data corruption or loss. Complex content models, broken relationships, and rich text formatting can all suffer during conversion, especially when dealing with localized data or large asset libraries.
That’s why migration testing should happen at multiple stages. First with automated checks (to confirm record counts, field types, and assets) and then with manual visual reviews to confirm that the content looks identical in Sanity Studio and on the frontend.
Once you’ve assessed the risks, decide how much of the existing structure should carry over. There are two approaches you can take:
Keep your existing structure: A fast and low-risk path where you move the current setup to Sanity without major refactoring. It’s ideal if your main goal is to reduce costs or overcome Contentful’s limitations without redesigning your data model.
Rebuild and migrate: A more strategic option where you use a custom script to redesign your content structure for long-term flexibility. This approach takes more time but gives you complete control over how your CMS evolves.
If you’re unsure, start by migrating the current setup using the official tool, confirm stability, and then iterate with schema improvements later. For small to mid-sized projects, this hybrid approach often completes in just a few days, as long as there are no missing dependencies or complex plugin integrations.
Option 1: Migrate Using the Official Contentful-to-Sanity CLI
The fastest way to transfer your content from Contentful to Sanity is to use the official CLI tool, contentful-to-sanity. It exports all your data, converts it into Sanity’s format, and even generates matching schema files. You can have a working Sanity Studio in minutes.
Step 1: Get Your Contentful Credentials
To run the script, you’ll need three API keys from your Contentful account:
Space ID – easiest to copy from your project URL, e.g. https://app.contentful.com/spaces/[projectURL]/views/entries or find it under Settings → Space Settings → General Settings
Content Delivery API token – create one in Settings → API Keys.
Content Management API (CMA) token – generate it under Account Settings → CMA Tokens. You can then generate a new token by clicking the top-right button:
Tip: Set your token to expire in 1–30 days. One day is fine for testing, thirty for production
Step 2: Run the Migration Script
Now that you have your keys, run the CLI command:
npx contentful-to-sanity@latest -s <space-id> -t <cma-token> -a <Content Delivery API - access token> ./output-path
If tokens are correct, you’ll see logs of the export. A 401 error means one of the keys is invalid.
CLI output showing successful export of Contentful data for migration to Sanity.
After the script finishes, you’ll find these files in your output directory:
contentful.json and contentful.published.json – raw exports from Contentful
dataset.ndjson – data formatted for Sanity import
schema.ts – auto-generated schema matching your Contentful models
Files generated by the Contentful-to-Sanity migration script, ready for import into Sanity.
At this stage, you’re about halfway done. The data is ready, and the schema is mapped.
That will allow us to add new schemas later without impacting the auto-generated file. Now, it’s time to test our new CMS system with the schema.
Run npm run dev to preview your new Studio. You should see something like this:
On the left, you can see all of the content types, which will be empty for now. Remember their names, before we move on to the next step: data migration.
Step 4: Import Your Content
Copy dataset.ndjson into your project and run:
npx sanity dataset import ./dataset.ndjson
dataset.ndjson file ready for import into Sanity Studio
Select your dataset (default: production).
Successful data import
After the import completes, your entries will appear inside Sanity Studio.
Sanity Studio view
Next, you should update your fetching methods in the NextJS app to use the new data source.
Step 5: Update Your Queries
Replace your Contentful GraphQL API with Sanity’s GROQ-based client.
We need to update our API calls and queries. Since Contentful uses GraphQL queries, let’s start by converting them into GroQ queries. If you’re struggling with this part, consider using an AI to help.
The -> sign is very important here. When a field is a reference to another document, by default, we only get the reference id. To get real values from this reference and resolve it, you need to use -> syntax.
Step 6: Update the Code
After updating the queries, we can now focus on updating the code where we fetch the data. Right now, your setup is fetching all posts and uses the GraphQL, Contentful URL, and access tokens.
Update all of the places where you fetch the data from Contenful to use Sanity.
You can still use GraphQL in this scenario. Go to the official Sanity docs and see how to implement that. It requires a few additional steps, like deploying the API on every change to the schema.
Step 7: Update the Richtext
Now we need to update the richtext component. Contentful uses its own logic to store and render the richtext markdown. Sanity has a different approach and its own pattern to keep this kind of data using the PortableText component, which we will apply now.
We need to define the components we want to use for each block type and replace the old Markdown renderer. Update the markdown component to something similar to this one:
Congratulations! This should be enough to transfer the CMS and convert your UI to use Sanity data and richtext. Now all that’s left to do is to focus on adding extra features, plugins like preview, which, in my opinion, is a must-have for editors.
Get curated tech news from Pagepro delivered to your inbox every month.
Option 2: Create Your Own CMS Migration Script
If the official CLI tool doesn’t work for your project, for example, because you use nonstandard plugins or highly customized content types, you can create your own migration script.
This path takes longer, but it gives you full control over field mapping, schema design, and data validation.
The custom-script path takes longer, but it gives full control. Once your schemas are right, mapping is easy and the output clean and predictable.
Rafał Dąbrowski, Developer at Pagepro
Step 1: Export Data from Contentful
Start by installing the official CLI:
npm install -g contentful-cli
Log in to your Contentful account:
contentful login
Then export your space data:
contentful space export --space-id <your-space-id>
You should see a similar screen to the one from contentful-to-sanity script:
CLI output confirming successful export of Contentful data for migration to Sanity.
This command generates a .json file containing your full space data. It includes contentTypes, entries, assets, and localization information.
For custom migrations, ignore contentTypes and focus on entries.
Each entry’s sys object tells you what content type it belongs to, along with its ID and relationships. You’ll use this data to identify how fields map to your new schema.
Now we see that we have a type of page. We can analyze the fields we have here.
Step 2: Define Your Sanity Schemas
In a fresh Sanity project, start by creating schemas that match your data model. Below is an example of defining SEO metadata and Page document types.
Let’s start working on the script. It will map the data from the old system into sanity schemas and generate an .ndjson for easy import.
First, we need to read the input file and then find the correct data from the input file and extract the required data. Then we map this data to a new schema and generate the NDJson file that we can use for import.
Now that you have a working base, focus on creating and refining your schemas. Once you’re satisfied with their structure, adjust your script to map each field correctly, as shown in the example. Getting the schemas right is the most time-consuming – and important – part of this migration. Once that’s done, mapping the data is straightforward.
When your output looks correct, import it into Sanity and continue with the next steps outlined the step 4 in Option 1: updating rich text rendering and adding any plugins you need.
Some teams use alternative methods, like web scraping, to extract content. If that approach fits your project better, it’s worth exploring.
Conclusion
Migration is a process that rewards preparation. With a clear plan, backups, and a careful approach, anybody can migrate Contentful to Sanity.
How long it takes depends entirely on your goals. If you’re simply moving to Sanity for better flexibility and are happy with your current data model, the process can be very quick. But if you’re rebuilding schemas or adding new features, treat it as an opportunity to refine your CMS structure for the long term.
Above all, never skip testing. Validate your redirects, metadata, and content relationships before the final switch. A few extra rounds of automated and manual checks can save you from downtime, broken links, and SEO drops.
Are you having problems with your CMS migration? Don’t hesitate to ask us for help!
Teams move from Contentful to Sanity for greater flexibility, customization, and predictable costs. Contentful’s model isn’t easily customizable either.
Sanity, on the other hand, lets developers define their own content models, add custom input components, and collaborate in real time. It works better for growing teams that need control without the limits of a closed ecosystem.
Why is Contentful So Expensive?
The biggest issue with Contentful’s pricing is the steep jump between the free and paid tiers. The free plan is generous for individual developers, but for teams only a few content types and users are allowed. The next available plan costs roughly $300/month, which comes with additional purchases like different types of spaces.
Is Sanity CMS Free?
Yes. Sanity offers a free forever plan suitable for small projects, MVPs, and personal sites. Paid plans start at around $15 per user/month, adding collaboration features, increased API limits, and additional datasets.
How Long Does it Take to Migrate Contentful to Sanity?
Migration time depends on your setup. Using the official CLI tool, a simple project can be moved in a day or two. For larger projects with custom content models, the process can take a few weeks.
What’s the Difference Between Using the CLI Tool and Writing a Custom Script for Migration?
The CLI tool is fast and automated. It exports data from Contentful, converts it into Sanity’s format, and even generates schema files. Writing a custom migration script takes longer but gives you total control. You can redesign schemas, fine-tune data mapping, and decide exactly how relationships and fields are structured.
Can I Migrate Assets, Such as Images and PDFs, from Contentful to Sanity?
Yes. The official CLI handles assets automatically, while a custom script requires you to include them manually using the assets array and Sanity’s upload API.
Why Do Companies Migrate Contentful to Sanity?
Teams move from Contentful to Sanity for greater flexibility, customization, and predictable costs. Contentful’s model isn’t easily customizable either. Sanity, on the other hand, lets developers define their own content models, add custom input components, and collaborate in real time. It works better for growing teams that need control without the limits of a closed ecosystem.
Why is Contentful So Expensive?
The biggest issue with Contentful’s pricing is the steep jump between the free and paid tiers. The free plan is generous for individual developers, but for teams only a few content types and users are allowed. The next available plan costs roughly $300/month, which comes with additional purchases like different types of spaces.
Is Sanity CMS Free?
Yes. Sanity offers a free forever plan suitable for small projects, MVPs, and personal sites. Paid plans start at around $15 per user/month, adding collaboration features, increased API limits, and additional datasets.
How Long Does it Take to Migrate Contentful to Sanity?
Migration time depends on your setup. Using the official CLI tool, a simple project can be moved in a day or two. For larger projects with custom content models, the process can take a few weeks.
What’s the Difference Between Using the CLI Tool and Writing a Custom Script for Migration?
The CLI tool is fast and automated. It exports data from Contentful, converts it into Sanity’s format, and even generates schema files. Writing a custom migration script takes longer but gives you total control. You can redesign schemas, fine-tune data mapping, and decide exactly how relationships and fields are structured.
Can I Migrate Assets, Such as Images and PDFs, from Contentful to Sanity?
Yes. The official CLI handles assets automatically, while a custom script requires you to include them manually using the assets array and Sanity’s upload API.