TrademarkTrademark
Features
Documentation

How to Export State from Terraform Cloud

Three working ways to get state out of Terraform Cloud (CLI, API, UI), why init -migrate-state fails, and what you can't export at all.
Ryan FeeJuly 20, 2026
Key takeaways
  • The quickest export is `terraform state pull > terraform.tfstate`, run per workspace from a directory with the workspace's cloud or remote block configured.
  • `terraform init -migrate-state` does not work in the outbound direction: moving state from Terraform Cloud to another backend is unimplemented in the CLI as of July 2026, so the pull-then-push sequence is the supported path.
  • For bulk export, script the State Versions API: each state version exposes a hosted-state-download-url, and the documented rate limit of 30 requests per second per user is comfortable for hundreds of workspaces.
  • The State Versions API rejects organization tokens; authenticate with a user or team token that has read-state-versions permission, or every request 404s.
  • Sensitive variable values are write-only and never come back through the API or UI, so plan to re-enter them on whatever platform you move to.
  • Deleting a workspace deletes its state with no documented recovery path. Export first, delete second.

HashiCorp ships official tooling for moving state into Terraform Cloud. There's tf-migrate, there are docs, there's a guided flow. In the other direction you get an error message. Everything about exporting state out of the platform, whether you're moving to an S3 bucket or another management platform, is assembled from a CLI command, an API, and a workspace page in the UI. This post covers all three, plus the two things you can't export at all.

Everything here was verified against HashiCorp's live documentation and the current CLI behavior as of July 2026.

How do you export state from Terraform Cloud?

Run terraform state pull > terraform.tfstate from a working directory configured for the workspace. That's it for a single workspace: the command downloads the current state and writes it to stdout as raw JSON. For bulk export across many workspaces, script the State Versions API instead. The web UI covers the one-off case with a per-version download link. As of July 2026 there is no official HashiCorp tool that exports state out of the platform, so pick the route that matches your workspace count.

The CLI route in full:

terraform login          # once, stores a user API token
terraform init           # connects to the workspace via your cloud block
terraform state pull > terraform.tfstate

One caveat worth knowing before you archive these files: state pull upgrades the state to the format of your locally installed Terraform version before writing it out. If you need the byte-identical original, download it through the API or UI instead, which serve the stored file as-is.

Does terraform init -migrate-state work for leaving Terraform Cloud?

No. Swap the cloud block for a backend block, run terraform init -migrate-state, and current Terraform versions answer: "Migrating state from Terraform Cloud to another backend is not yet implemented." Inbound migration is a first-class feature; outbound is not. The gap has been tracked in hashicorp/terraform#31042 since 2022, with a companion docs issue (#33214) still open as of July 2026.

The supported sequence is manual, and it works reliably:

  1. terraform state pull > terraform.tfstate while the cloud block is still in place.
  2. Remove the cloud block and add your new backend block (S3, GCS, azurerm, or a remote block pointing at another platform).
  3. terraform init against the new backend.
  4. terraform state push terraform.tfstate to seed it.

If the push complains about serials or lineage, you're pushing into a backend that already has state in it. How to update state in a remote backend covers those checks and how to resolve them safely.

How do you download state through the API?

Two endpoints do the work. GET /state-versions?filter[workspace][name]=<ws>&filter[organization][name]=<org> lists a workspace's versions, newest first; GET /workspaces/:workspace_id/current-state-version returns just the latest. Each result carries a hosted-state-download-url you fetch with the same token. One authentication rule matters more than everything else: these endpoints reject organization tokens. Use a user token, or a team token with the read-state-versions permission.

A minimal single-workspace export:

# TFC_TOKEN must be a user or team token, not an org token
URL=$(curl -s \
  --header "Authorization: Bearer $TFC_TOKEN" \
  "https://app.terraform.io/api/v2/state-versions?filter%5Bworkspace%5D%5Bname%5D=my-workspace&filter%5Borganization%5D%5Bname%5D=my-org" \
  | jq -r '.data[0].attributes."hosted-state-download-url"')
 
curl -s --header "Authorization: Bearer $TFC_TOKEN" "$URL" > my-workspace.tfstate

Two details for bulk scripts. First, the list endpoint paginates with page[number] and page[size] (20 per page by default), so archiving full history means walking pages, not grabbing .data[0]. Second, HashiCorp's documented rate limit is 30 requests per second per user, and it's enforced per user rather than per token, so parallel tokens won't raise it. At roughly three requests per workspace, that's still hundreds of workspaces a minute. Each state version also exposes a hosted-json-state-download-url serving a stable external-integration format, which is the better choice if other tooling will parse the files.

Can you download state from the Terraform Cloud UI?

Yes, one version at a time. Every workspace has a States page listing each state version alongside the run and commit that produced it. Click a version and you get a diff against the previous state plus a link to the raw state file. It's fine for grabbing one file during debugging, and useless for fleet export: there's no bulk download, and nobody wants to click through 300 workspaces.

What can't you export from Terraform Cloud?

Two things. Sensitive variable values are write-only: the variables API returns them as null and the UI never shows them again, so budget migration time for re-entering secrets from whatever manager originally held them. And deleted state is gone: HashiCorp's own docs state that once a workspace and its state are deleted, the infrastructure can no longer be tracked or managed, with no documented recovery path. The safe-delete default only refuses to delete workspaces still managing resources; it does nothing to preserve state files. Export first. Delete second.

How do you export state from every workspace at once?

Loop the API, or use migration tooling that does it for you. A bash loop over the state-versions endpoint handles the raw export fine at fleet scale. If the export is step one of a platform move, here's where the tooling stands as of July 2026. HashiCorp's tf-migrate only moves state into HCP Terraform or Terraform Enterprise. tfm, from HashiCorp's implementation services team, handles org-to-org and Enterprise-to-Cloud moves but carries a "not officially supported" label in its README. Scalr's TFC migration tool pulls workspaces through the same API and preserves the full state-version history rather than just the current file, recreates workspace attributes and variables, and recovers sensitive Terraform variable values from plan files when they're available.

Where the export lands depends on why you're leaving. Teams going self-managed put state in object storage and accept the locking and backup work that comes with it. Teams moving platform-to-platform should size the whole job first, not just the state step: our migration effort and timeline breakdown covers what the other steps cost in practice. State import is free on Scalr's side either way, and the free tier covers 50 runs a month, which is enough to validate a batch of migrated workspaces before any money changes hands.

For the full decision framework beyond the mechanics, see the platform engineer's guide to replacing Terraform Cloud.

Frequently asked questions

How do I export state from Terraform Cloud?

Run `terraform state pull > terraform.tfstate` in a working directory configured for the workspace (after terraform login and terraform init). For many workspaces, script the State Versions API: list versions per workspace, then download each hosted-state-download-url with a user or team token. The web UI also offers per-version downloads on the workspace's States tab.

Does terraform init -migrate-state work for moving state out of Terraform Cloud?

No. As of July 2026 the Terraform CLI returns 'Migrating state from Terraform Cloud to another backend is not yet implemented' when you swap the cloud block for a backend block and run init -migrate-state. The working sequence is: pull state to a local file, remove the cloud block, add the new backend block, run terraform init, then terraform state push.

Why does the Terraform Cloud state API return 404 with my token?

The State Versions API explicitly rejects organization tokens. Generate a user token or a team token whose team has the read-state-versions permission on the workspace. This is the most common trip-up in export scripts, because org tokens work fine for many other endpoints.

Can I export sensitive variables from Terraform Cloud?

No. Values marked sensitive are write-only: the variables API returns them as null, and the UI never displays them again. When you migrate, re-enter sensitive values from your secrets manager. Some migration tooling, like Scalr's TFC migration tool, can recover sensitive Terraform variable values from recent plan files when they're available, but the API itself never returns them.

Do I lose state history when I leave Terraform Cloud?

Only if you export just the latest version. The State Versions API lists every historical version per workspace, and each has its own download URL, so a script can archive all of them. Scalr's migration tool preserves the full state-version history when it moves a workspace; a plain state pull grabs only the current version.

What happens to state if I just delete my Terraform Cloud workspace?

It's deleted with the workspace, and HashiCorp's documentation offers no recovery path afterwards. Safe-delete only blocks deletion while the workspace is still managing resources; it doesn't protect the state file. Download every state version you care about before deleting anything.
About the author
Ryan Feedirector of platform engineering at Scalr
Ryan Fee is the director of platform engineering at Scalr, with over 15 years of experience improving infrastructure experiences at companies large and small.