---
title: "Slack Canvas to Google Docs Migration | ClonePartner"
description: "Slack Canvas to Google Docs: Every text insertion into a Google Doc shifts subsequent character positions forward in UTF-16 code units…"
source: Slack Canvas
target: Google Docs
canonical: "https://clonepartner.com/migrate/slack-canvas-to-google-docs"
---

# Slack Canvas → Google Docs migration

Slack Canvas to Google Docs migration — canvases exported with their structure and channel context preserved.

## Why teams migrate from Slack Canvas to Google Docs

Migrating from Slack Canvas to Google Docs requires a fully custom-built pipeline, as no native export path or direct conversion tool exists between the two platforms. Slack Canvases are extracted as markdown via the canvases.getContent API method, then reconstructed in Google Docs using index-based insert requests through the documents.batchUpdate endpoint. The fundamental data model difference is that Slack Canvases use a flat markdown content string while Google Docs use a positional index system measured in UTF-16 code units, requiring precise offset tracking to avoid index drift that corrupts formatting. Additional custom work is required to handle image re-hosting, OAuth scope configuration for both APIs, rate limit management on both platforms, and the hard limitation that Slack canvas revision history cannot be migrated through any available API method.

## Key migration challenges

- **Index Drift in batchUpdate** — Every text insertion into a Google Doc shifts subsequent character positions forward in UTF-16 code units, requiring requests to be ordered in descending index position or built with a carefully tracked cursor to prevent formatting from being applied to incorrect document ranges.
- **No Canvas Enumeration Endpoint** — Slack provides no dedicated <code>canvases.list</code> method, requiring engineers to use the general <code>files.list</code> endpoint filtered to <code>types=canvas</code>, which only surfaces canvases accessible to the authenticated token and will silently under-count without a Workspace Admin user token.
- **Dual API Rate Limit Management** — Both Slack's Tier 3 limit of 50+ requests per minute on <code>canvases.getContent</code> and Google's 60 writes per minute per user cap on <code>documents.batchUpdate</code> must be independently managed with exponential backoff and jitter to avoid cascading 429 failures across the pipeline.
- **UTF-16 Character Index Calculation** — Google Docs API indexes are measured in UTF-16 code units rather than Unicode characters, meaning emoji and other non-BMP characters each consume two index positions, causing naive character-count-based offset calculations to silently corrupt document structure in emoji-heavy canvases.
- **Image Re-hosting Requirement** — Inline images embedded in Slack Canvases must be downloaded via <code>files.info</code> using a Slack user token and re-hosted at a publicly accessible URI before the Google Docs API's <code>InsertInlineImageRequest</code> can reference them, or the request returns a non-retryable 403.
- **Canvas Revision History Hard Limitation** — Slack's API surface exposes only the current published version of a canvas through <code>canvases.getContent</code>, making full edit history permanently inaccessible and impossible to migrate regardless of pipeline design or engineering effort.

## Entity mappings

- **Standalone Canvas** (Slack Canvas) → **Document** (Google Docs)
- **Channel Canvas** (Slack Canvas) → **Document** (Google Docs)
- **Canvas Content (Markdown)** (Slack Canvas) → **Paragraph** (Google Docs)
- **Table** (Slack Canvas) → **Table** (Google Docs)
- **Checklist** (Slack Canvas) → **List** (Google Docs)
- **Image** (Slack Canvas) → **InlineImage** (Google Docs)
- **File Attachment** (Slack Canvas) → **Link** (Google Docs)
- **Comment** (Slack Canvas) → **Comment** (Google Docs)
- **Channel** (Slack Canvas) → **Google Drive Folder + Google Doc Index Page** (Google Docs)
- **User** (Slack Canvas) → **Permission** (Google Docs)

## What breaks during migration

- **Canvas Text Content** [Workaround] — Plain text body content transfers reliably as markdown, but accurate reconstruction in Google Docs requires correct UTF-16 index tracking and reverse-ordered batch requests to prevent formatting corruption.
- **Heading Styles and Formatting** [Breaks] — Applying heading styles via <code>updateParagraphStyle</code> requires precise <code>startIndex</code> and <code>endIndex</code> values that are invalidated by index drift if insertion order is not carefully managed, making formatting the most failure-prone element of the migration.
- **Inline Images** [Breaks] — Images must be individually downloaded from Slack using authenticated requests and re-hosted at public URLs before Google Docs insertion, adding significant pipeline complexity and a hard dependency on external hosting availability.
- **Tables** [Breaks] — Tables occupy variable amounts of index space in Google Docs, compounding index drift calculations and requiring precise offset accounting for every cell insertion and any subsequent formatting applied to table ranges.
- **Canvas Revision History** [Breaks] — Slack's API exposes no endpoint for canvas version or edit history, making this data permanently unmigratable and representing an absolute data loss for any workflow that depends on audit trails or historical content states.
- **User Mentions** [Workaround] — Slack <code>@mention</code> tokens must be resolved to display names via the <code>users:read</code> scope before insertion into Google Docs, as the raw user ID format has no meaning in the Google Workspace context.
- **Canvas Metadata and Ownership** [Workaround] — Ownership, creation timestamps, and channel linkage metadata from <code>files.list</code> can be captured during inventory but must be manually mapped to Google Drive file properties, as Google Docs has no native equivalent for Slack's <code>linked_channel_id</code> or <code>is_channel_space</code> fields.
- **Standalone vs. Channel-Linked Canvases** [Workaround] — Standalone canvases require explicit sharing to be visible to the migrating token, meaning canvases not proactively shared with the admin user will be silently omitted from inventory and therefore from the migration entirely.
- **Large Canvases Near Size Limits** [Breaks] — Google Docs enforces an approximately 1,020,000 character limit per document, and canvases approaching this threshold will produce a non-retryable 400 error on <code>batchUpdate</code>, requiring preflight size validation and a document-splitting strategy before migration begins.
- **OAuth Scope Configuration** [Direct] — Required scopes for both APIs are well-documented and static for this pipeline, but a missing scope produces a 403 that is indistinguishable from a permission error at runtime, making upfront scope verification essential to avoid misleading debugging cycles.

## What we migrate

### Migration Filter

- **Time Range** — Migrate articles created or updated within a specific period
- **Language & Locale** — Migrate specific language versions or translations only
- **Category Selection** — Select specific sections, folders, or categories to migrate
- **Publication Status** — Filter by published, draft, archived, or internal-only articles

### Data Types

- **Tags & Metadata** — SEO settings, search labels, author attribution, and article tags
- **Articles & Content** — Core help articles including HTML formatting and inline images
- **Media & Attachments** — All downloadable files, PDFs, and media assets embedded in articles
- **Categories & Hierarchy** — Full folder structure with sections, sub-sections, and parent categories

## Complete technical guide

For a deep-dive into the technical process, data mapping, and step-by-step migration workflow, read our full guide: [Slack Canvas to Google Docs Migration: API Limits & Data Mapping](https://clonepartner.com/blog/slack-canvas-to-google-docs-migration-api-limits-data-mapping/).

## Frequently asked questions

### Is there a native way to migrate Slack Canvas to Google Docs?

No. There is no built-in migration path. You must extract canvas content as markdown via canvases.getContent, transform it, and rebuild each document through the Google Docs API's documents.batchUpdate endpoint.

### What is index drift in the Google Docs API?

Index drift occurs when inserting content at one position shifts all subsequent character indexes forward. Google's documentation recommends ordering batchUpdate requests in descending index order to avoid this. Failing to handle it corrupts formatting and misplaces content.

### How do you list all Slack Canvases via the API?

There is no canvases.list endpoint. Use files.list filtered to type canvas (GET https://slack.com/api/files.list?types=canvas). This is a Tier 3 method allowing 50+ requests per minute per workspace.

### Can you embed images directly into Google Docs via the API?

No. The InsertInlineImageRequest requires a uri field with a publicly accessible HTTPS URL. You must first upload Slack-hosted images to Google Drive or a public storage bucket, then reference that URL in the insert request.

### What are the character limits for Slack Canvas vs Google Docs?

Slack Canvas document_content is capped at 1,048,576 characters (1 MiB). Google Docs is limited to approximately 1.02 million characters. The gap is roughly 28,000 characters, so most canvases fit, but near-limit documents should be checked before conversion.

## Get a fixed-price quote

[Talk to an engineer](https://clonepartner.com/talk-to-us?duration=30&utm_source=xtoy&utm_medium=button&utm_campaign=demo_bookings&utm_content=cta_click&utm_term=demo_button_click) about your Slack Canvas → Google Docs migration.
