markitdown4j converts documents to Markdown from Java, as a CLI or a library
markitdown:Cli;Lib; Java
At a glance
- What is it?
- markitdown4j is a Java 11 rewrite of Microsoft's MarkItDown that turns PDFs, Office documents, HTML and archives into Markdown, delivered both as a shaded JAR and as an embeddable library with OCR support and YAML configuration. It is a young project at version 0.0.4, built in the context of an open source rewrite competition, and the Java surface is the reason to look at it.
- Who is it for?
- Adopt markitdown4j when your document ingestion pipeline already lives in Java and you need Markdown output with warnings, metadata and OCR in one call, and you are willing to track a project at version 0.0.4. Do not adopt it outside the JVM, where the original MarkItDown is the shorter path, and do not expect the feature set of a mature release, since the version numbering and the test tags show how young it is.
- Can I use it commercially?
- Yes. MIT 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?
- Yes. The repository last received commits 160 days ago.
- What is it written in?
- Mainly Java, 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
A Java rewrite of Microsoft's document converter
markitdown4j is described as a Java implementation of a document to Markdown converter, positioned as a Java rewrite of Microsoft MarkItDown and as a delivery for an open source rewrite competition. Both of those framings matter for how you read the project.
The rewrite framing explains the shape of the tool. MarkItDown comes from a different ecosystem, so a Java version has to reproduce the behaviour in another language, and the Java idioms show through. The competition framing explains the delivery. The version is 0.0.4, the release list includes a tag literally named v0.0.2-test for test files, and the version table in the README lists a single current version rather than a history.
What the project delivers is one set of conversion capabilities exposed in two product shapes. The CLI is for end users, for local conversion, for scripts and for automation. The Java Library is for integrators, for embedding the conversion into services, toolchains and business systems. The README makes the point that the library is not an add-on but one of the two forms of the product.
The engine is Java 11, the build is Maven, and the licence is MIT. The main artefact is a shaded JAR, target/markitdown4j-0.0.4.jar, which means the CLI runs from a single file with no separate classpath assembly.
Building the JAR and running the CLI
The build requirements are JDK 11, Maven 3.8 or newer, and, if you plan to use the tesseract-cli OCR engine, a Tesseract executable installed on the system.
Building is a standard Maven package:
mvn clean packageThe CLI is then the JAR file, and the README is careful about this point. The name markitdown4j in the examples is a documentation convention, and the equivalent command is:
java -jar target/markitdown4j-0.0.4.jarIf you have not created an alias or a wrapper script of your own, use the java -jar form. That warning exists because the examples throughout the README are written with the short name, and a reader who has not installed an alias will get an unrecognised command instead of a helpful error.
The general form of the command is:
markitdown4j [options] <input...>The inputs are flexible. Local files, directories, HTTP(S) URLs and standard input streams are all accepted, and the tool can handle a single file, a whole directory in batch mode, or several files in sequence.
Batch, remote inputs and the OCR flags
The examples in the README cover the four situations you are likely to meet.
A single PDF to a Markdown file:
markitdown4j report.pdf -o output.mdA directory converted in batch mode into an output directory:
markitdown4j ./docs --batch -o out/A file fetched over the network:
markitdown4j https://example.com/report.pdf -o out/And OCR on a scanned document, where the engine is named explicitly:
markitdown4j scan.pdf --ocr --ocr-engine tesseract-cli -o output.mdThat last line is the one to remember, because the OCR engines are different animals. tesseract-cli runs a locally installed Tesseract and works across platforms. The http engine talks to a custom HTTP OCR service, which is how you would point the tool at a PaddleOCR server you operate. The paddleocr engine uses the PaddleOCR task interface directly.
Three configuration commands round out the CLI surface:
markitdown4j --generate-config
markitdown4j --validate-config
markitdown4j --show-configThe first writes a configuration file, the second checks it against the validation rules, and the third prints the configuration that is actually in effect. In a pipeline where the effective settings matter, --show-config is the one worth remembering.
YAML configuration with a four level precedence chain
The configuration model is described as YAML-first, and the precedence order is explicit. Built-in defaults come first, then markitdown.yml, then markitdown.local.yml, and CLI overrides come last. Anything passed on the command line beats both files.
Three filenames are recognised: markitdown.yml, markitdown.local.yml and markitdown.example.yml. The split between the first two is a familiar convention. The first is the configuration you commit, the second is the one you keep out of the repository for local settings, and the example file documents the shape of the file.
The Java side mirrors the same model with ConversionOptions, a runtime options object built through a builder. The documented builder methods cover what each output should contain and how:
ConversionOptions options = ConversionOptions.builder()
.includeMetadata(true)
.includeImages(true)
.includeTables(true)
.tableFormat("github")
.imageFormat("markdown")
.useOcr(true)
.ocrEngine("tesseract-cli")
.language("eng")
.tesseractPath("O:/tesserOCR/tesseract.exe")
.tessdataPath("O:/tesserOCR/tessdata")
.maxFileSize(0)
.build();Two of those lines are worth attention. The table format and image format are strings, so the output shape is a matter of configuration rather than recompilation, and the tesseractPath and tessdataPath options let you point at a local Tesseract installation, which matters on Windows where the executable is rarely on PATH. maxFileSize set to zero means no size limit.
The README also states that extracted images can be written into a resources directory next to the output.
The library API: engine, options and a result object
The library surface is small enough to read in one sitting. MarkItDownEngine is the main conversion entry point, ConversionOptions carries the runtime settings, ConversionResult holds the Markdown, the metadata, the warnings and a status, and DocumentConverter is the extension contract for adding your own converter. ConversionException is the checked exception for a failed conversion, and MarkItDownApplication provides a convenience entry point with createEngine().
A minimal file conversion looks like this:
MarkItDownEngine engine = MarkItDownApplication.createEngine();
try {
ConversionOptions options = ConversionOptions.builder().build();
ConversionResult result = engine.convert(Path.of("report.pdf"), options);
if (result.isSuccessful()) {
System.out.println(result.getMarkdown());
} else {
System.err.println(result.getWarnings());
}
} finally {
engine.shutdown();
}Two details in that snippet are design decisions rather than syntax. The result object is checked with isSuccessful() before the Markdown is read, and warnings are treated as output rather than as an exception. And the engine owns runtime resources, so the documentation asks you to call shutdown() when you are done, to avoid leftovers in a long-lived process.
For streams there is an overload taking an InputStream and a MIME type, and the engine also offers asynchronous and batch entry points: convertAsync for a Path and for an InputStream, convertParallel for a list of paths, and convertAll for a list of paths.
Before converting, you can ask the engine whether it can handle a given input, either as a path or as a MIME type:
boolean supportedPath = engine.isSupported(Path.of("input.pdf"));
boolean supportedMime = engine.isSupported("application/pdf");The library is installed into a local Maven repository with mvn clean install and consumed with the coordinates com.markitdown:markitdown4j:0.0.4.
Formats, failures and how errors surface
The format list is split in two. The main formats are PDF, DOCX, XLSX, HTML and HTM, TXT and Markdown, CSV, JSON and XML, images, and ZIP archives. A second group has dedicated handling logic: DOC, PPTX, PPT, XLS and audio.
The README lists the supported formats without describing the quality of the conversion for any of them, and that is the honest limit of the documentation available here. If your pipeline depends on table structure in a spreadsheet or on reading order in a multi-column PDF, you have to check that yourself.
The failure catalogue is more specific. Conversion fails when the file does not exist or cannot be read, when the MIME type cannot be recognised or no converter is available for it, when the OCR engine is unavailable or fails, when the input exceeds the size limit, and when a remote download fails.
The handling of those failures differs by form, and the distinction is the point. In the CLI they become diagnostic messages aimed at the user. In the library they surface through the result object and through exception handling, so a caller can decide whether a failed document should abort the batch or be logged and skipped.
For the asynchronous and parallel APIs, the same result object carries the warnings, which is how you keep a per-document audit trail when converting hundreds of files.
Version 0.0.4, an MIT licence and a competition entry
The maintenance picture is simple to state. The last push to the default branch was on 2026-05-16, the repository is not archived, and the released version is 0.0.4, published on the same day. Before that, v0.0.3 arrived on 2026-05-03 with multi-platform artefacts, a unified OCR provider and PaddleOCR integration, and v0.0.2-test on 2026-03-23 carried test files.
A version number below 1.0 and a test release tag in the history are the honest signals here. The project is early, the API may still move, and the documentation set reflects that, since the index lists separate usage, configuration, testing and development documents in both Chinese and English, and the repository carries a verification directory and a project_tools directory.
The licence is MIT, which keeps adoption simple for commercial use and for redistribution, provided the notice travels with the code.
The practical advice for a team evaluating this is to treat it as a well-documented young library rather than a settled dependency. Read configuration.md for the YAML keys and validation rules before writing your own configuration, read usage.md for the command patterns and output rules, and read testing.md for the current test inventory and the manual verification commands, since the project publishes those commands rather than asking you to trust the description.
Editorial conclusion
Adopt markitdown4j when your document ingestion pipeline already lives in Java and you need Markdown output with warnings, metadata and OCR in one call, and you are willing to track a project at version 0.0.4. Do not adopt it outside the JVM, where the original MarkItDown is the shorter path, and do not expect the feature set of a mature release, since the version numbering and the test tags show how young it is. Before you commit, build it with JDK 11 and Maven 3.8, run markitdown4j --validate-config against your own YAML, and check that your PDF and Office inputs produce the Markdown you need, since the documentation lists the supported formats without describing the fidelity of any of them.
Frequently asked questions
How do I build and run the markitdown4j CLI?
With JDK 11 and Maven 3.8 or newer, run mvn clean package and then run the shaded JAR with java -jar target/markitdown4j-0.0.4.jar. The README notes that the shorter markitdown4j name in its examples is only a documentation convention unless you create an alias or wrapper script.
How do I add markitdown4j as a Maven dependency in a Java service?
Install it into your local repository with mvn clean install and depend on com.markitdown:markitdown4j:0.0.4. The main entry point is com.markitdown.core.MarkItDownEngine, obtained through MarkItDownApplication.createEngine().
Which OCR engines does markitdown4j support?
Three: tesseract-cli, which uses a locally installed Tesseract across platforms, http, which calls a custom HTTP OCR service, and paddleocr, which uses the PaddleOCR task interface. The engine is selected with the --ocr-engine option or the ocrEngine option on ConversionOptions.
Which file formats can markitdown4j convert to Markdown?
The main formats are PDF, DOCX, XLSX, HTML and HTM, TXT and Markdown, CSV, JSON, XML, images and ZIP archives, and DOC, PPTX, PPT, XLS and audio have dedicated handling logic. The engine also accepts HTTP(S) URLs and standard input streams.
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/duanyan007-markitdown)Was this useful?