All formats

MuPDF

LanguageC (C++, Java, Python, JavaScript and .NET bindings)
LicenseAGPL-3.0 or commercial license from Artifex
Repositorygithub.com/ArtifexSoftware/mupdf
Documentationmupdf.readthedocs.io
Depends onbundled third-party libraries (freetype, harfbuzz, zlib, libjpeg, gumbo and others)
Read / writeyes / no (unencrypted MOBI with no compression or PalmDOC compression)

MuPDF is a document rendering library (PDF, XPS, EPUB, FB2, CBZ) that also opens Mobipocket files. It recognizes a file by the BOOKMOBI or TEXtREAd signature, decompresses the text records, collects the image records, and lays out the result with its HTML engine. After that, a MOBI file works like any other MuPDF document: count pages, render, extract or search text, convert to PDF.

MuPDF’s MOBI support is basic. It handles uncompressed and PalmDOC-compressed text in Latin-1, Windows-1252 or UTF-8, but not HUFF/CDIC compression (used by many books made with Amazon’s tools) or DRM. It reads the text records as one HTML document, as in MOBI 6, and doesn’t use the EXTH metadata. For full MOBI and KF8 parsing use libmobi. The AGPL license requires you to publish your source code if you distribute your program or offer it as a network service.

Installation#

Shell
# Debian / Ubuntu
sudo apt install libmupdf-dev
# Fedora
sudo dnf install mupdf-devel
# macOS
brew install mupdf
# Windows (vcpkg)
vcpkg install mupdf

Link with -lmupdf (static builds also need -lmupdf-third).

Basic usage: open a MOBI file and extract text#

C
#include <mupdf/fitz.h>
#include <stdio.h>

int main(int argc, char **argv) {
    if (argc < 2) {
        fprintf(stderr, "usage: %s book.mobi\n", argv[0]);
        return 1;
    }
    fz_context *ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED);
    if (!ctx) return 1;

    fz_document *doc = NULL;
    fz_buffer *buf = NULL;
    fz_var(doc);
    fz_var(buf);
    fz_try(ctx) {
        fz_register_document_handlers(ctx);
        doc = fz_open_document(ctx, argv[1]);
        fz_layout_document(ctx, doc, 420, 595, 11);  // page size in points, font size

        int n = fz_count_pages(ctx, doc);
        for (int i = 0; i < n; i++) {
            buf = fz_new_buffer_from_page_number(ctx, doc, i, NULL);
            fputs(fz_string_from_buffer(ctx, buf), stdout);
            fz_drop_buffer(ctx, buf);
            buf = NULL;
        }
    }
    fz_always(ctx) {
        fz_drop_buffer(ctx, buf);
        fz_drop_document(ctx, doc);
    }
    fz_catch(ctx) {
        fz_report_error(ctx);  // e.g. "unknown compression method" for HUFF/CDIC books
        fz_drop_context(ctx);
        return 1;
    }
    fz_drop_context(ctx);
    return 0;
}

fz_open_document detects MOBI by content, so .azw and .azw3 files open too when they use a supported compression.

How to render a MOBI page to PNG#

C
fz_matrix ctm = fz_scale(2, 2);  // 144 dpi
fz_pixmap *pix = fz_new_pixmap_from_page_number(ctx, doc, 0, ctm, fz_device_rgb(ctx), 0);
fz_save_pixmap_as_png(ctx, pix, "page1.png");
fz_drop_pixmap(ctx, pix);

How to convert MOBI to PDF#

C
fz_document_writer *wri = fz_new_document_writer(ctx, "book.pdf", "pdf", NULL);
int n = fz_count_pages(ctx, doc);
for (int i = 0; i < n; i++) {
    fz_page *page = fz_load_page(ctx, doc, i);
    fz_device *dev = fz_begin_page(ctx, wri, fz_bound_page(ctx, page));
    fz_run_page(ctx, page, dev, fz_identity, NULL);
    fz_end_page(ctx, wri);
    fz_drop_page(ctx, page);
}
fz_close_document_writer(ctx, wri);
fz_drop_document_writer(ctx, wri);

From the command line: mutool convert -o book.pdf book.mobi.

How to check that a file is MOBI before opening it#

fz_lookup_metadata with FZ_META_FORMAT returns MOBI for Mobipocket files:

C
char format[64];
if (fz_lookup_metadata(ctx, doc, FZ_META_FORMAT, format, sizeof format) > 0)
    printf("format: %s\n", format);

Tips#