pptx2md: turning PowerPoint decks into markdown with the heading structure intact
a pptx to markdown converter
At a glance
- What is it?
- pptx2md converts a .pptx file into markdown, and the work it does beyond text extraction is the structure: a title list file with indentation as the level marker, fuzzy matching with an accept threshold of 92, pictures extracted to disk and referenced by relative path, and tables with merged cells kept as tables. It can also emit TiddlyWiki wikitext, Madoko or Quarto markup instead of markdown.
- Who is it for?
- Adopt pptx2md if you have a folder of decks that need to become documentation, notes or a site, and you need the heading hierarchy to be right rather than every slide title flattened to the same level.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Activity is slowing. The repository last received commits 6 months ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What the converter promises to preserve
The README lists the formats it preserves, and the list is where the value of the tool sits. Titles are preserved, with a custom table of contents and fuzzy matching supported. Lists are preserved with arbitrary depth. Text keeps its bold, italic, colour and hyperlink formatting. Pictures are extracted into image files with a relative path inserted in the output. Tables are preserved including merged cells, which is the part most converters get wrong. And the block order is top to bottom and then left to right, which is the reading order of a slide rather than the order the shapes happen to sit in the XML. The tool also supports several output languages beyond markdown, which is what makes it usable for a documentation pipeline rather than only for a quick paste. The scope is the newer .pptx format, and the README is explicit that older .ppt files are not supported and have to be converted first.
Four output targets, one set of switches
Markdown is the default output, and the alternatives are TiddlyWiki's wikitext, Madoko and Quarto, which is an unusually wide set for a converter this small. The switches are `--wiki` and `--mdk` for the first two, and `--qmd` for the Quarto markup used by Quarto powered presentations, which the README links to the Quarto documentation. The reason this matters is that the conversion is not only a text extraction. A deck converted to Madoko markup and then rendered produces a document that looks like a document, and the README's own screenshots show exactly that comparison, with the source pptx on the left and the generated markdown rendered by Madoko on the right. The picture handling has a parallel set of switches, with `--image-width` setting a maximum width in pixels and the note that if it is set the images are emitted as an HTML img tag instead of plain markdown, plus `--disable-image` to skip extraction entirely, `--disable-notes` to leave out presenter notes, `--disable-escaping` to skip escaping special characters, and `--disable-color` to leave out the colour tags in HTML output.
The title list is where the document structure comes from
By default the tool parses every pptx title into a level 1 markdown title, which gives you a flat list and not a document. The fix is the title file, passed with `-t`, and the convention in it is simple. Indentation is the level, so two spaces means the second level and four spaces the third, and the sample file in the README shows exactly that shape with a heading, two indented subheadings, one further indented and one not, and then the next top level heading. A line of ` Heading 1.1` is therefore output as `## Heading 1.1` and ` Heading 1.1.1` as `### Heading 1.1.1`. The titles in your deck are matched to the list with fuzzy matching, and the parse rules section gives the threshold, a matching score must be greater than 92 for a match to be accepted, and unmatched pptx titles are treated as the deepest header level. There is a related behaviour for near-duplicate slide titles, which are omitted by default unless `--keep-similar-titles` is passed, in which case the repeated title gets a continuation marker.
How a slide becomes blocks, lists and text
The detailed parse rules explain the extraction model, and they are worth reading because they define what you will and will not get. Text blocks are identified in two ways, paragraphs that are marked as body placeholders in the slide, and text shapes that contain more than the minimum block size, which is configurable with `--min-block-size`. Lists are generated when the paragraphs inside a block have different indentation levels, and single level paragraphs are emitted as regular text blocks. Multi-column layouts can be detected with `--try-multi-column`, which the arguments list flags as very slow, so it is a tool for a specific deck rather than a default. Grouped shapes are recursively flattened so their contents are processed, and shapes are processed in top to bottom, left to right order. The formatting mapping is direct, with bold converted to `**bold**`, italic to `_italic_` and a hyperlink preserved as a link with its text and URL, while colour handling preserves theme colours marked as Accent 1 through Accent 6 and otherwise works from the RGB values.
Windows metafile images are the one external dependency
The `badblocks`-free problem in this tool is WMF, and the README has a specific line for it. The `--disable-wmf` switch keeps WMF formatted images untouched, which the arguments list explains is to avoid exceptions under Linux, and separately the README advises installing wand for a better chance of successfully converting WMF images if you need it. The dev dependencies list confirms that, with wand pinned in the development group, which tells you it is not a runtime requirement of the published package but a helper for the conversion step. The rest of the image pipeline is ordinary, with extracted pictures landing in an `/img/` folder by default and the directory configurable with `-i`, and the output file defaulting to `out.md` with the path settable through `-o`. Two more switches are useful in a batch context, `--page` to convert only a specified page, and `--enable-slides` to delimit slides with a horizontal rule, which the README says helps when you want to convert pptx slides into markdown slides.
The same options are available from Python
The tool is usable as a library, and the API mirrors the command line exactly. You import `convert` and `ConversionConfig` from the package, and the configuration object takes the same parameters as the arguments, with the input path, the output path and the image directory as required, and the rest optional, including the title path, the image width, the disable flags for images, escaping, notes, WMF and colour, the slide delimiters, the multi-column attempt, the minimum block size, the wiki, mdk and qmd output flags, the page number and the keep similar titles switch. The example in the README shows a basic conversion with the notes disabled.
from pptx2md import convert, ConversionConfig
from pathlib import Path
# Basic usage
convert(
ConversionConfig(
pptx_path=Path('presentation.pptx'),
output_path=Path('output.md'),
image_dir=Path('img'),
disable_notes=True
)
)That symmetry is the design decision that makes the tool scriptable, because a batch conversion does not have to shell out and parse the command line, and it means the flag set does not drift between the two interfaces.
Packaging, tooling and one licence question
The project is a Poetry package with the console script declared as `pptx2md = "pptx2md.__main__:main"`, and the runtime dependencies are small and legible, with python-pptx for reading the file, rapidfuzz for the title matching, Pillow for image work, tqdm for progress, pydantic for the configuration model, and numpy and scipy alongside them. The build uses poetry-core, and the Makefile has two targets, a format target that runs pycln, isort and yapf, and a publish target that builds with poetry and uploads with twine. The style configuration is in the same file, with yapf on the Google style at a column limit of 120, isort on the hug profile, and pycln configured to clean the package directory. The version in the manifest is 2.0.6, the last push was on 2026-04-21, and the repository publishes no GitHub releases, so PyPI is the version history. One detail deserves a look before you redistribute anything, because the package metadata declares the licence as an MIT licence while the repository's own licence file is recorded as Apache 2.0, and those are different terms with different obligations.
Editorial conclusion
Adopt pptx2md if you have a folder of decks that need to become documentation, notes or a site, and you need the heading hierarchy to be right rather than every slide title flattened to the same level. Do not expect it to read the legacy binary .ppt format, which the README says is unsupported, and check the licence position yourself before redistributing output, because the package metadata declares an MIT licence while the repository's own licence file is recorded as Apache 2.0. Before converting a large deck, read the parse rules, because the block detection uses a minimum text size and the multi-column detection is described as very slow. The package version is 2.0.6, the last push was on 2026-04-21, and the repository publishes no GitHub releases.
Frequently asked questions
How do I install and run pptx2md?
You need Python later than 3.10 with pip, then run `pip install pptx2md` and use the command `pptx2md [pptx filename]`. The default output file is `out.md`, and extracted pictures are placed in an `/img/` folder. Older .ppt files are not supported and have to be converted to .pptx first.
How do I control the heading structure of the converted markdown?
Pass a title file with `-t`. Indentation in that file is the heading level, so two spaces gives a level two heading and four spaces a level three, the titles in the deck are matched with fuzzy matching, a match needs a score greater than 92 to be accepted, and unmatched titles are treated as the deepest header level. Use `--keep-similar-titles` if you want repeated slide titles kept with a continuation marker.
Can pptx2md output something other than markdown?
Yes. The supported outputs are markdown, TiddlyWiki wikitext via `--wiki`, Madoko via `--mdk`, and the Quarto markup used by Quarto powered presentations via `--qmd`. The same options exist on the `ConversionConfig` class for programmatic use.
How does pptx2md handle WMF images?
The `--disable-wmf` switch leaves WMF formatted images untouched, which the README says avoids exceptions under Linux, and the README advises installing wand for a better chance of converting WMF images successfully. Wand is a development dependency of the package rather than a runtime one.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/ssine-pptx2md)Was this useful?