Skip to content

Parse Scientific PDFs: Install GROBID 0.9.1

Deploy GROBID 0.9.1 to parse scientific PDFs into TEI XML. Exact Docker commands, RAM specs, health checks, and 0.9.x upgrade traps.

6 min readIntermediate

Stop pasting papers into demo cloud boxes. If you need to parse scientific PDFs at any real volume, you self-host GROBID 0.9.1 and hit a local API. Demos throttle, change, and vanish. A container on your machine does not.

Output you actually want: TEI XML with headers, body sections, figures/tables, and references – something a RAG index or citation graph can swallow without layout cleanup. This page is a deploy runbook for the current stable tag, not a feature tour.

System requirements (before you pull)

Docker is the supported path on Linux, macOS, and Windows. Native builds target Linux 64-bit and macOS (Intel/ARM). Windows native is flaky; use Docker there.

Resource Minimum Recommended
Docker Working engine Desktop or Engine with enough VM RAM on Mac/Windows
RAM to the container 2 GB (header only) 4 GB fulltext; 6-8 GB heavy parallel batches (Grobid-docker troubleshooting)
Disk ~0.5 GB for CRF image ~14 GB free for full image + workspace
CPU x86_64 or arm64 (CRF) Multi-core; NVIDIA GPU + CUDA on Linux for full image speed
Source build only OpenJDK 21+ Same + optional Python 3.10-3.11 / GPU for DeLFT

CRF if you care about disk and CPU throughput. Full if citation/header quality is the bottleneck and you can spare ~14 GB – plus a Linux GPU when you have one. Habit is a bad picker here.

Official download sources for GROBID 0.9.1

Use these only – mirrors lag and old tags still float around blog posts.

As of the 0.9.1 tag (August 2026), compressed Hub sizes sit around 486 MB (crf, amd64) and 13.8 GB (full, amd64). Recheck the Hub if you read this later – layers move.

Install GROBID 0.9.1 with Docker (recommended)

Install Docker from the official installer for your OS. Then pick one flavor.

Option A – Lightweight CRF (bulk CPU, small disk)

docker pull grobid/grobid:0.9.1-crf

docker run --rm --init --ulimit core=0 
 -p 8070:8070 
 --name grobid 
 grobid/grobid:0.9.1-crf

Option B – Full image (higher citation/header quality; GPU on Linux)

docker pull grobid/grobid:0.9.1-full

docker run --rm --gpus all --init --ulimit core=0 
 -p 8070:8070 
 --name grobid 
 grobid/grobid:0.9.1-full

No NVIDIA card? Drop --gpus all. Full still runs on CPU – slower. Want metrics? Map admin too: -p 8070:8070 -p 8071:8071.

On Apple Silicon, prefer multi-arch CRF. Amd64-only layers acting up? Pin the platform:

docker run --rm --init --ulimit core=0 
 --platform linux/amd64 
 -p 8070:8070 grobid/grobid:0.9.1-crf

--ulimit core=0 keeps the native PDF layer from filling the container with core dumps. --init reaps zombies.

Alternative: build from source (dev only)

wget https://github.com/grobidOrg/grobid/archive/0.9.1.zip
unzip 0.9.1.zip && cd grobid-0.9.1
# path must NOT contain spaces
./gradlew clean build
./gradlew run

OpenJDK 21+ on the PATH. For routine parsing jobs, stay on Docker.

Funny how much of “PDF AI” still dies on ops details – not model choice. Memory floors, a stale yaml key, a path with a space. Get those wrong and the fancy TEI never shows up.

First-time configuration (minimum viable)

Defaults already process PDFs. Concurrency or model tweaks? Copy grobid.yaml on the host and mount it read-only – absolute host path required:

docker run --rm --init --ulimit core=0 
 -p 8070:8070 -p 8071:8071 
 -v /absolute/path/to/grobid.yaml:/opt/grobid/grobid-home/config/grobid.yaml:ro 
 grobid/grobid:0.9.1-crf

Pro tip: Custom yaml carried from 0.8.x still holding server.maxQueuedRequests? Delete that line before 0.9.1. Dropwizard 5 / Jetty 12 dropped the field; the process throws ConfigurationParsingException / unrecognized field and exits. That is the classic “image pulled, container dies instantly” failure on this release (see the project Upgrading notes).

0.9.1 also fail-fasts when the install path contains spaces and the Wapiti/CRF engine is in play. And pdfalto temp no longer quietly assumes a global /tmp – it follows grobid.temp under grobid-home. If extractions look “empty” after a custom mount, check that temp dir is writable inside the container.

Verify the install works

First boot loads models. Give it a minute.

# Liveness (plain true/false)
curl -s http://localhost:8070/api/isalive

# Version string + git revision
curl -s http://localhost:8070/api/version

# Readiness JSON (engines / init state)
curl -s http://localhost:8070/api/health

# Smoke-test a real PDF
curl -s -X POST http://localhost:8070/api/processFulltextDocument 
 -F "input=@./sample.pdf" -o out.tei.xml

# Optional: browser console
open http://localhost:8070

isalivetrue, TEI file non-empty: you can parse scientific PDFs end-to-end. Port 8071 (when mapped) is admin/metrics.

Common install errors and fixes

Symptom Likely cause Fix
Container killed mid-PDF Docker RAM too low Docs put the floors at ~2 GB header, ~3 GB citations, ≥4 GB fulltext; 6-8 GB for parallel clients
Unrecognized field "maxQueuedRequests" Stale 0.8 yaml on 0.9.1 Remove that key from the server: block
500 BAD_INPUT_DATA Corrupt, encrypted, or awkward PDF Open the file locally; try another PDF – often not a server misconfig
500 NO_BLOCKS Scanned / image-only PDF OCR first, then resubmit
Rosetta / AVX / SSE4.1 crashes on Mac amd64 full image under emulation 0.9.1-crf arm64, or --platform linux/amd64 with more RAM; skip full DL on weak hosts
GPU libs missing (Windows/WSL) --gpus without NVIDIA stack Run without --gpus, or fix NVIDIA Container Toolkit on Linux
Build fails / native libs odd Spaces in install path Move the tree; 0.9.1 fail-fasts on spaces with CRF/Wapiti

Older tags under newer Docker Desktop also show cgroup/JVM weirdness in community threads. Pin 0.9.1-*; skip random latest mirrors.

Upgrade from previous versions / uninstall

docker stop grobid 2>/dev/null; docker rm grobid 2>/dev/null
docker pull grobid/grobid:0.9.1-crf
# rerun your docker run line

Images ship matching models. No separate model hunt on a straight Docker bump.

The catch is 0.8.x → 0.9.x on source builds: JDK 21 required; DL stack moves to TensorFlow 2.17, Python 3.10-3.11, DeLFT ≥0.4.x – custom DL models must be retrained. 0.9.1 itself is mostly the Dropwizard 5 / Jetty 12 refresh on top of 0.9.0. After cutover, /api/version should read 0.9.1.

Uninstall / cleanup:

docker stop grobid; docker rm grobid
docker rmi grobid/grobid:0.9.1-crf grobid/grobid:0.9.1-full
docker image prune -f
# source installs: delete the grobid-0.9.1 directory

FAQ

Which image should I run to parse scientific PDFs daily?

0.9.1-crf. Move to 0.9.1-full only when citation F1 is the bottleneck and you have disk (and ideally a Linux GPU).

How do I know GROBID 0.9.1 actually started?

curl -s http://localhost:8070/api/isalive must return plain true (HTTP 200). Then /api/version should say 0.9.1. Orchestrators: isalive = liveness, /api/health = readiness.

Can I skip Docker and only use a public demo?

For one PDF, sure – poke a Hugging Face demo space. For a corpus? No. Cold starts, rate limits, no SLA. That is why this guide ends at a local :8070. Point the official Python client or plain curl at your box and batch folders. If fulltext 500s while isalive stays green, inspect Docker memory and the PDF before reinstalling.

Next: pull grobid/grobid:0.9.1-crf, run the command above, POST one of your own papers to /api/processFulltextDocument, and do not stop until out.tei.xml is on disk.