Skip to content
Back to Blog
August 18, 202613 min read

How to convert ChatGPT (or Claude) output to a Word document — without uploading it anywhere

Open this tool

Every model I use writes in Markdown. Ask ChatGPT for a project brief, Claude for a risk summary, Gemini for a comparison table, and the answer comes back with ##in front of the headings and pipe characters holding the table together, because Markdown is what these models were trained to emit and what the chat window renders. That is fine right up to the moment somebody asks for it "as a Word doc". I hit that moment often enough, and cleaned up the resulting mess by hand often enough, that I eventually built Markdown to Word: paste the reply, get a real .docx, and the document never leaves the browser tab.

This post is about why the two obvious routes fail, what a conversion can and cannot carry across, and when you should ignore our tool entirely and use pandoc instead.

Why pasting into Word doesn't work

There are two ways to get a chat reply onto your clipboard, and they fail differently. It is worth understanding both, because the second one fails in a way that looks like success.

Route one: the copy button

ChatGPT and Claude both put a copy button under every reply. That button copies the Markdown source, not the rendered answer. Your clipboard ends up holding one flavour, text/plain, and Word renders text/plain as plain text. So you get:

  • ## Q3 Revenue with the hash marks still sitting in front of the heading
  • **up 14% YoY** with the asterisks wrapped around the text that was supposed to be bold
  • - [ ] Follow up with legal as a hyphen, a bracket, a space and another bracket, instead of a checkbox
  • the table as a wall of pipes and hyphens that, in a proportional font like Aptos or Calibri, does not even line up as ASCII art. It is a paragraph of punctuation.

People reasonably expect Word's AutoFormat to catch this. It doesn't. AutoFormat As You Type is keystroke-driven: it watches what you type and reacts when you press space or Enter, which is why typing # then a space really does give you a Heading 1. A paste is not keystrokes. It arrives as one block, and nothing fires. Microsoft has been steadily adding Markdown affordances to Word, so it is worth checking your own build, but a pasted block of Markdown is still just text.

Route two: select the rendered answer and copy

Now the clipboard carries text/html, and Word has an HTML importer. This is the route that produces results people describe as "almost right, but wrong in a way I can't fix".

The thing to understand is what Word's HTML paste actually is. Word does not have a browser inside it. Its HTML importer is a converter: it walks the markup and maps the subset it recognises onto OOXML constructs, a <table> onto <w:tbl>, an <h2> onto the Heading 2 style, <b> onto <w:b/>. The CSS it recognises it bakes in as direct formatting on the individual runs and paragraphs. Anything it does not recognise is approximated or discarded. There is no layout pass and no fallback rendering: a construct either has an entry in that map or it does not exist. Three consequences follow, and they are the three things people complain about.

Tables survive, but as somebody else's tables.The column widths arrive as pixel values lifted from the chat interface's stylesheet, sized for a chat column rather than for your page's text width, so a five-column table either overruns the right margin or gets crushed into a strip. Borders, padding and header shading arrive as direct formatting on every individual cell, and in OOXML direct formatting wins over style formatting. That is why the Table Styles gallery stops working after a paste: you click a style, and nothing visibly changes, because every cell is already overriding it. To get control back you have to select the table and clear the formatting, which also clears the alignment you wanted to keep.

Code blocks arrive as a picture of code, in text form. The chat UI colours each token with its own <span>, and the importer turns every one of those colours into direct character formatting. If you were reading in dark mode, you now have pale grey text on white paper. Whether the block's dark background comes with it as paragraph shading is a coin flip, so sometimes you get contrast and sometimes you get invisible code. Indentation is the other casualty: leading whitespace only survives if the importer honours the preformatted white-space handling, and nested code frequently comes out flattened toward the left margin. Because all of it is direct formatting, changing the document font afterwards does nothing to it.

Equations mostly vanish.Chat interfaces render LaTeX with a browser math renderer, which emits two things at once: a MathML copy for accessibility, hidden from view, and a visual rendering built out of ordinary positioned spans in the renderer's own fonts, which is what draws the fraction bar, the radical and the integral sign. Word's HTML importer has no MathML support, so the half that genuinely is the equation gets dropped. What survives is the scaffolding: a run of characters in a font you probably do not have installed, with the absolute positioning that arranged them removed. An integral over a fraction comes out as a line of loose symbols in roughly the wrong order. Diagrams do worse. A Mermaid chart rendered as inline SVG has no entry in the map at all, so it simply is not there when you paste.

None of this is Word being badly built. It is the predictable behaviour of a format converter that people use as though it were a rendering engine.

Why "just use an online converter" is the wrong reflex

Search for "markdown to word" and most of the first page is upload boxes. Choose a file, wait, download. It works, and for a throwaway document it is fine. For a work document it is a category error.

Uploading means the bytes leave your machine and land on a disk you do not control. Between here and there, a copy plausibly exists in a TLS terminator's access log, a job queue, a worker's temp directory, a nightly backup and possibly an antivirus scanner. "Files are deleted after one hour" is a policy, not a mechanism. It might well be true. You have no way to check, and no recourse if it is not.

But retention is not even the main argument. For a work document, the disclosure is the event. If you are under an NDA, if your employer has a data-classification policy, if you are a lawyer with a duty of confidentiality, a clinician anywhere near patient data, or an engineer at a company whose customer contracts enumerate their approved sub-processors, then sending the file to a vendor nobody vetted is the breach. It happens at upload, regardless of what the vendor does next. You cannot un-send it, and you often cannot even tell your security team which company received it, because the converter is a domain name, an ad stack and a privacy policy nobody has updated in years.

It is also worth being honest about what people actually convert. Nobody converts a shopping list. The documents that need to become .docx are the unsigned contract, the salary band table, the incident post-mortem, the roadmap that has not been announced, the diligence memo. Model output is worse than average here, because a reply usually restates the context you fed it: the client's name, the figures you pasted in, the internal codename for the project.

One caveat, because the argument is often overstated: this is an argument against cloud converters, not against every alternative. Pandoc runs entirely on your own machine and is exactly as private as anything described here. If you already have it installed, skip to the comparison below.

Converting a ChatGPT or Claude reply, step by step

  1. Copy the reply with the chat's own copy button. This is the one time that button's behaviour is exactly what you want: the Markdown source is the input format here.
  2. Open Markdown to Word and paste into the left pane. If your Markdown is already a file, drop a .md or .txt onto the page instead. Either way the content is read in your browser; there is no upload step and no account.
  3. Read the preview on the right. This is the part worth slowing down for. The preview is not decoration, it is how the converter parsed your Markdown. If a table looks like a table there, it will be a table in Word. If it looks like a paragraph of pipes, the model emitted a malformed table and you want to know that now rather than in front of a client.
  4. Pick a Word theme.Default is Word's own Aptos/Calibri look and is the safest choice for a document somebody else will edit. GitHub is Segoe UI with tighter spacing, for technical notes. Academic is Times New Roman at 12pt with 1.5 line spacing, for anything with a submission style guide attached.
  5. Turn on Equations or Diagrams if your document needs them. Both engines load only the first time you flip the switch, which is why they are switches: roughly 85 KB compressed for the maths engine, and between about 350 KB and 460 KB for Mermaid depending on which diagram types you use. Equations become native m:oMath, the same markup Word's own equation editor writes, so you can click one in Word and edit it instead of getting a flat picture. Mermaid fences become real images in the file.
  6. Leave "Fetch remote images" off unless you need it. Off is the default, and off is what makes the next paragraph true.
  7. Download the .docx, or copy instead. If the document you want this in is already open, skip the file entirely: Copy for Word / Docs puts formatted HTML on your clipboard next to a plain-text copy, so a paste into Word, Google Docs, Outlook or Gmail keeps the headings, bold text and tables. It needs the async clipboard API on a secure page, so where the browser lacks it the button is disabled and says why.
  8. Read the notes panel. Anything the converter could not carry across is listed there rather than silently dropped. More on that below.

On speed: the conversion is measured, not estimated. On the build that is live now, 0.25 MB of Markdown converts in about 0.50 s, 0.5 MB in 0.84 s, 1 MB in 1.79 s, and 2 MB somewhere between roughly 2.3 s and 4.3 s depending on the machine, with a 2 MB document measured end to end in Chrome at about 3.1 s. The work runs in a Web Worker, so the page keeps scrolling and the editor keeps taking keystrokes while it happens; the worst main-thread stall we measured on a 2 MB document was 117 ms. Input is capped at 2 MB because packing an OOXML package is super-linear: 4 MB measures at roughly 13 seconds and about 3 GB of memory, which is enough to kill a tab on a phone. Rather than hang and hope, the tool refuses the document and tells you by how much you are over.

On privacy, precisely. With remote images off, the converter makes zero network requests. Not encrypted in transit, not deleted after an hour: zero. Parsing and OOXML packing both run as JavaScript in your tab. What is honest to add, and what most tools blur, is that the claim is about the converter and not about the page. This page, like every page on this site, loads Google Analytics, and pressing Download fires one event carrying the theme name, three booleans, the input and output sizes in bytes, a duration and a count of notices. Numbers and closed enums only; the analytics helpers do not accept a free-form string, so a file name or a line of your text could not be put into one even by accident. Your draft is kept in the browser's own local storage so a reload costs you nothing, and Clear deletes it.

What does not survive the conversion

Every article about converting Markdown to Word tells you what works. This is the part they leave out, and it is the part that decides whether you can trust the rest.

  • Raw HTML becomes literal text. If your Markdown contains a <div> or a <br>, the .docx shows you those characters rather than acting on them. This is deliberate, and it is also the single place the preview disagrees with the file, because a browser renders that markup and Word does not receive it. If a model hands you HTML instead of Markdown, ask it again for Markdown.
  • Syntax colours do not come across. Code arrives as a shaded monospace block with a named style on it, which is what Word wants, but the site passes no highlighter to the converter, so a Python block and a JSON block look identical. The code is intact. It is just monochrome.
  • Remote images are refused by default. Every http(s) image becomes an [image: alt text] placeholder in both the preview and the file, and the notes panel counts them. Turning the toggle on embeds them for real, and is the only thing that makes the converter touch the network at all: your browser then requests each URL, and those hosts see your IP address. Images written as data: URLs are embedded either way.
  • There is no table of contents field.A Word TOC is a field, meaning OOXML stores the instruction and not the entries, so a generated one arrives empty until the reader updates it. Word prompts on open or updates on F9, LibreOffice has Tools then Update, and Google Docs and Pages do not run fields at all, so there it stays blank forever. Rather than ship something that looks broken to half the people who open it, the tool emits none. Headings come through as genuine Heading 1 to 6 styles, so Word's navigation pane already works and References then Table of Contents builds a filled-in one in a click. A literal TOC marker, incidentally, renders as a list in the preview and stays as text in the file.
  • Anything Markdown cannot express. Headers and footers, page numbers, a cover page, section breaks, margins beyond what the theme sets, numbered captions, cross-references, comments and tracked changes. Markdown has no syntax for any of it, so no converter can invent it. You get the content; the page furniture is a two-minute job in Word afterwards.
  • Documents over 2 MB. The cap is a refusal, not a truncation, so you never get a silently half-converted file.
  • Diagrams the engine cannot draw. With Diagrams off, mermaid fences stay code blocks. With it on, a fence Mermaid rejects also stays a code block and gets listed in the notes. Mermaid needs a real DOM to measure text and a canvas to rasterise the result, so that one pass runs on the page rather than in the Worker, which is the one architectural wart in the whole pipeline.
  • Equations, if their engine fails to load. They come through as their TeX source, and the notes panel says so.

That list is longer than the ones you will find elsewhere, on purpose. A converter that quietly drops something is worse than one that carries less and says which parts it could not carry, because the first kind costs you a proofread you did not know you needed.

An honest comparison

CapabilityMarkdown to WordPandocCloud convertersGoogle Docs pasteRaw paste into Word
SetupOpen a URLInstall a binary, use a terminalOpen a URLGoogle account, enable MarkdownNone
Where the document goesStays in the tabStays on your machineUploaded to a third partyUploaded to GoogleStays on your machine
TablesReal Word tablesReal Word tablesUsuallyNot supportedLiteral pipe characters
FootnotesReal Word footnotesReal Word footnotesVariesNoNo
EquationsNative, editable (toggle)Native, editableVariesNoNo
Mermaid diagramsImages in the file (toggle)With an external filterRarelyNoNo
Your organisation's templateThree built-in themesAny reference .docxRarelyDocs styles onlyWhatever you paste into
Citations and bibliographyNoYes, with CSL stylesNoNoNo
Table of contents fieldNo (headings are real styles)YesVariesDocs outline insteadNo
Batch and scriptingNo, one document at a timeYes, built for itSome offer an APINoNo
Live preview before you commitYesNoSometimesIt is the documentNot applicable
CostFree, no accountFree and open sourceFree tier, then paidFree with an accountFree

Read that table honestly and pandoc wins it. That is the correct conclusion, and a comparison table that concluded otherwise would be a sales brochure. Pandoc is a mature document-conversion system with two decades behind it; we wrote a converter for one direction of one format pair. What follows is which situation each one is actually for.

Use pandoc when

You can install software, and either the document has to match your organisation's real Word template, or there is more than one of it. --reference-doc lets you point pandoc at an existing .docx and inherit its actual style definitions, which is something three built-in themes will never match. Add --citeproc and a CSL file and you have proper citations and a bibliography. It reads dozens of input formats and writes dozens more, it takes filters so you can transform the document tree between the two, and it is scriptable, so a folder of 300 files is a loop rather than an afternoon. It also runs entirely locally, so nothing in the confidentiality section above counts against it.

pandoc brief.md -o brief.docx --reference-doc=house-style.docx

Use ours when

You cannot install anything, or you should not have to. A locked-down work laptop, a client's machine, a borrowed desktop, a phone: a URL works on all of them and a Haskell binary works on none of them. You want to see the parse before you open Word, because model output is not always well-formed and the preview is where you find that out. Or you want the clipboard route, which pandoc has no equivalent of: there is no pandoc flag for "put formatted content on my clipboard so I can paste it into the document I already have open". And when the person who needs the conversion is a colleague in operations rather than an engineer, the honest comparison is between sending them a link and talking them through a package manager.

About Google Docs' Markdown paste

It deserves a fair hearing, because it is genuinely good and genuinely free. Turn on Markdown under Tools then Preferences, and pasted Markdown gets converted as it lands: headings, bold, italic, strikethrough, links, bulleted and numbered lists, checklists, blockquotes and code. For a prose document that is going to live in Docs anyway, that is the shortest path there is, and you can export .docx from Docs afterwards.

The gaps are tables, footnotes and maths, none of which are on Google's supported list, and tables are exactly what model output is full of. Google keeps extending this, so check it against your own document rather than taking a blog post's word for it. Worth noting too that it is also an upload, to Google, which may be completely fine for your document or may be precisely the thing your policy forbids. Our Copy for Word / Docs button aims at the same window from the other side, which is why the button names Docs.

Why we built it, and where the code is going

The unglamorous origin: we write client-facing documents for a living. A proposal gets drafted with an assistant in the loop, the scope section comes back in Markdown, and the client wants a .docx. Doing that by hand is paste, delete the hash marks, re-apply Heading 2, hunt the asterisks, rebuild the table cell by cell, notice the numbered list restarted at one. Twenty minutes, and what you hand over is a document carrying forty direct-formatting overrides that will fight whoever edits it next.

We looked at what existed. Pandoc was installed on our machines and on none of our clients'. Cloud converters were off the table for a document with a client's name in the first paragraph. So we wrote the converter as a standalone library, called downword: markdown-it on the front for parsing, a neutral document model in the middle, and an OOXML renderer on the back built on the docx package, with temml and mathml2omml handling the TeX-to-Word-equation path.

The middle model is the part worth describing. It imports nothing at all — not the parser, not the renderer, not even its own siblings — so markdown-it's vocabulary cannot leak forward into the renderer and OOXML's cannot leak back into the parser. Every node kind is a member of one discriminated union, so adding one makes the exhaustive switches fail to compile rather than silently skip it. That is why "raw HTML becomes literal text" is a policy written in one place instead of an accident that happened in five, and it is why the list of things that do not survive is a list we can actually enumerate.

The library is vendored into this site for now, and the plan is to release it under a permissive licence and publish it so the converter is auditable rather than merely described. Being straight about the current state: it is not published yet. There is no downword package on npm today and no public repository to point at, so we are not going to link one or print an install command that would fail. When it is up, this paragraph gets the links.

Try it on the reply you already have open

Copy a chat reply, paste it into Markdown to Word, glance at the preview, and download the file. If the document you need is a PDF rather than a Word file, the same Markdown goes through Markdown to PDF instead. Both are free, neither needs an account, and neither adds a watermark.