Alles →
Markdown.
Eine URL oder Datei rein, sauberes Markdown raus: Web-Seiten ohne Navigation und Cookie-Banner, PDF- und Office-Dokumente, Bilder, Audio und YouTube-Transkripte — für LLM-Kontexte, Notizen und Archive. Open Source (AGPL), läuft per Docker auf der eigenen Maschine.


Rohes HTML ist teurer Kontext
Wer eine Web-Seite an ein Sprachmodell gibt, schickt Navigationsleisten, Tracking-Skripte und Cookie-Banner gleich mit und bezahlt sie in Tokens. Ein Agent braucht den Text, nicht das Gerüst drumherum.
Dazu kommt: Viele Seiten liefern ihren Inhalt erst, wenn ein echter Browser sie ausführt. Einfache Extraktoren sehen dort nur ein leeres Gerüst. Und Inhalt kommt längst nicht mehr nur als Web-Seite, sondern als PDF, Office-Dokument, Bild, Audio oder Video.
Cloud-Konverter lösen das, beantworten aber die falsche Frage: Wer fremde Dokumente durch einen fremden Dienst schickt, gibt sie aus der Hand. Die Datenfrage verschwindet nicht dadurch, dass man sie auslagert.
Was es macht
PullMD nimmt eine URL oder eine Datei und gibt sauberes Markdown zurück. Keine Navigation, keine Werbung, kein Cookie-Banner — nur der Inhalt, der wirklich auf der Seite stand. Seit Version 3 nicht mehr nur Web-Seiten, sondern auch Dokumente, Bilder, Audio und YouTube.
PullMD läuft selbst gehostet auf der eigenen Maschine.
Was der Browser lädt:
<nav class="site-header">…</nav>
<div id="cookie-consent">Wir nutzen Cookies… [Alle akzeptieren]</div>
<aside class="ads"><ins data-gpt/></aside>
<article>
<h1>Wie Caching funktioniert</h1>
<p>Ein Cache ist eine Kopie, die näher am
Verbraucher liegt als das Original.</p>
<h2>Warum das hilft</h2>
<p>Weniger Wege, weniger Wartezeit…</p>
</article>
<script src="tracking.js"></script>
Was PullMD zurückgibt:
---
title: Wie Caching funktioniert
source: readability · quality: 1
---
# Wie Caching funktioniert
Ein Cache ist eine Kopie, die näher am Verbraucher liegt als das Original.
## Warum das hilft
Weniger Wege, weniger Wartezeit…
PWA
Im Browser installierbar, offline-fähig, mit Verlauf und Archiv, hell und dunkel — die Oberfläche für Menschen.
REST-API
GET /api?url=… — eine Zeile curl, sauberes Markdown zurück. Dazu Upload-Endpunkte für Dateien und lokales HTML.
MCP & Agenten
Statusloser MCP-Server mit drei Werkzeugen, OAuth 2.1 für claude.ai, Claude-Code-Skill als Download von der eigenen Instanz.
Die Kaskade
Eine Seite sauber auszulesen ist kein Problem mit einer Methode. Statische Seiten gehen leicht, JavaScript-Seiten brauchen einen echten Browser, manche Seiten liefern schon selbst Markdown. PullMD probiert nicht alles auf einmal, sondern geht die Stufen der Reihe nach durch und hört bei der ersten auf, die ein gutes Ergebnis liefert.
- Cloudflare Markdown — direkt von der Quelle. Manche Seiten liefern auf Anfrage schon Markdown. Dann ist die Arbeit getan, bevor sie anfängt.
- Statische Extraktion — Readability + Trafilatura. Zwei bewährte Extraktoren laufen über das rohe HTML. Ein Qualitäts-Score entscheidet, welches Ergebnis gewinnt.
- Echter Browser — Playwright · Chromium. Reicht das nicht, rendert ein headless Chromium die JavaScript-Seite vollständig. Danach wird neu extrahiert. Das ist die schwerste Stufe, und sie läuft nur, wenn die leichteren versagt haben.
Das Prinzip lässt sich übertragen. Für jede Anfrage einen Browser zu starten wäre einfach zu bauen und teuer im Betrieb. Die Kaskade kostet mehr Code und spart bei jedem einzelnen Aufruf. Fast jede gute Architekturentscheidung sieht so aus: mehr Mühe an einer Stelle, damit es überall sonst leichter wird.
Was es kann
- Beliebige Quellen. PDF- und Office-Dokumente, EPUB, Bilder (mit generierter Bildbeschreibung), Audio (Transkription) und YouTube-Videos mit Transkript und anklickbaren Zeitmarken. Reddit-Threads und Hacker-News-Diskussionen kommen samt Kommentarbaum. Per URL oder Upload.
- Drei Wege hinein. Eine PWA im Browser, eine REST-API (
GET /api?url=…) und ein MCP-Server für Agenten. Dazu ein fertiges Claude-Code-Skill als Download. Der MCP-Server meldet seine Werkzeuge selbst an, ganz ohne Prompt-Anleitung. - Der Link, der lebt. Jede Konvertierung bekommt eine feste 8-stellige Adresse. Wird sie aufgerufen und der Inhalt ist älter als eine Stunde, holt PullMD ihn frisch von der Quelle. Eine stabile URL, die immer aktuellen Inhalt liefert, etwa für Feeds.
- Anschluss an claude.ai. Ein vollständiger OAuth-2.1-Flow lässt die eigene Instanz als Custom Connector direkt in der claude.ai-Web-App authentifizieren. Kein Workaround, kein Bearer-Token von Hand.
Architektur
Ein kompakter Express-Kern orchestriert. Die rechenintensiven Teile sitzen in eigenen Containern: ein Trafilatura-Sidecar, ein Playwright-Sidecar mit Chromium, ein MarkItDown-Sidecar für Dokumente. Jeder ist optional. Fehlt einer, fällt nur seine Funktion weg, der Rest läuft weiter. Der Kern ist über Dependency Injection testbar gebaut — daher die über 700 Tests.
server.js Express-App-Factory, /api + SSE-Stream
lib/web.js Orchestrator der Kaskade, pickBest
lib/mcp.js statusloser MCP-Server, 3 Werkzeuge
lib/cache.js SQLite-Cache, 90-Tage-TTL, Share-IDs
*-sidecar/ Trafilatura · Playwright · MarkItDown
Ideen zum Mitnehmen
Wer PullMD nie braucht, kann hier trotzdem etwas mitnehmen — die Prinzipien, nach denen ich Software baue.
- Komplexität ist optional. Version 3 ohne jede Konfiguration verhält sich wie Version 2: nur Web-Seiten, sauberer Output. Jede Erweiterung ist opt-in und fällt sauber weg, wenn man sie nicht einschaltet. Ein Werkzeug, das sofort läuft, schlägt eines mit fünfzig Schaltern, die man erst verstehen muss.
- Für Agenten gebaut, nicht nur für Menschen. Der Body ist reiner Inhalt, sämtliche Metadaten stehen im YAML-Frontmatter. Das spart Tokens, und ein Agent muss keinen Fließtext zerlegen, um an die Quelle zu kommen.
- Sicherheit vor dem Release, nicht danach. Vor dem v3-Release lief ein eigener, gezielt feindseliger Sicherheits-Durchgang gegen den Code. Er fand echte Probleme — darunter eine YAML-Injection und einen Zip-Bomb-Angriffsvektor — bevor sie jemanden betroffen haben.
- Selbst hosten ist die Antwort auf die Datenfrage. Bildbeschreibung und Audio-Transkription laufen wahlweise gegen einen lokalen Modell-Server. Nichts muss eine Cloud sehen.
Was das mit Ihrem Unternehmen zu tun hat
PullMD ist ein Werkzeug für Entwickler. Aber die Entscheidungen dahinter sind dieselben, die ein Mittelständler treffen muss, der KI einsetzen will, ohne die Kontrolle über seine Daten abzugeben: Läuft das lokal? Was passiert, wenn der Cloud-Dienst ausfällt? Wer hat die Daten gesehen?
Genau dort arbeite ich — an der Brücke zwischen klassischer Microsoft-Infrastruktur und KI-Werkzeugen, die DSGVO-konform auf der eigenen Infrastruktur laufen. PullMD zeigt im Kleinen, wie das aussieht.
Schnellstart
Fertige Multi-Arch-Images liegen auf Docker Hub. Keine .env nötig, jede Variable hat einen sinnvollen Standard.
mkdir pullmd && cd pullmd
curl -O https://raw.githubusercontent.com/AeternaLabsHQ/pullmd/main/docker-compose.yml
docker compose up -d
# → http://localhost:3000
Status
Die aktuelle Version ist live: Web-Seiten plus Dokumente, Bilder, Audio und YouTube, dazu PWA, REST-API, MCP-Server und ein Claude-Code-Skill. Multi-Arch-Images (linux/amd64 · linux/arm64) liegen auf Docker Hub. Die oben angezeigte Versionsnummer wird beim Build live aus den GitHub-Releases geholt.
Wie es entstand
PullMD ist aus dem eigenen Bedarf gewachsen, Web-Inhalte sauber und selbst gehostet für LLM-Kontexte aufzubereiten, und seitdem über mehrere Versionen hinweg als offenes Projekt weiterentwickelt worden.
Die ganze Entwicklung ist im Blog dokumentiert, in neun Teilen: vom ersten Frust über zugemüllten Kontext bis zum v3-Umbau auf beliebige Quellen.
- PullMD Teil 1: Strg+A und der Junk-Kontext
- PullMD Teil 2: Vom Spec zum laufenden Container
- PullMD Teil 3: Mehr als Reddit, mehr als Readability
- PullMD Teil 4: Vom Tool für mich zum OSS-Projekt
- PullMD Teil 5: Reddit-Tag und die ersten Issues
- PullMD Teil 6: Multi-User-Pivot
- PullMD Teil 7: Spec-Compliant ist nicht genug
- PullMD Teil 8: Eine alte Regel
- PullMD Teil 9: Microsofts MarkItDown integriert — und drei Teile wieder rausgerissen
Häufige Fragen
Welche Formate wandelt PullMD in Markdown um?
Web-Seiten immer — inklusive Reddit-Threads und Hacker-News-Diskussionen mit vollem Kommentarbaum. Mit dem Dokumente-Sidecar dazu PDF, Word, PowerPoint, Excel, EPUB, ZIP, CSV, JSON und XML. Bilder (generierte Beschreibung), Audio (Transkription) und YouTube-Transkripte sind Opt-in-Erweiterungen.
Läuft PullMD auch ohne Docker?
Ja. Der Kern ist eine normale Node.js-Anwendung: git clone, npm install, npm start — läuft auf Port 3000. Docker Compose ist nur der bequemste Weg, weil er die optionalen Sidecars gleich mitbringt.
Braucht die YouTube-Transkription einen API-Key?
Nein. Der Dokumente-Sidecar holt Titel, Beschreibung und Transkript ohne YouTube-API-Key; Zeitmarken kommen wahlweise als klickbare Links, Klartext oder gar nicht. Einzige Einschränkung: Rechenzentrums-IPs drosselt YouTube — dafür gibt es eine optionale Proxy-Variable.
Was passiert mit meinen Daten?
Alles bleibt auf der eigenen Maschine: Konvertierungen landen in einer lokalen SQLite-Datenbank und werden 90 Tage nach dem letzten Zugriff aufgeräumt. Hochgeladenes lokales HTML wird nie gecacht. Nur wer Bild-Beschreibung oder Audio-Transkription gegen eine Cloud-API konfiguriert, schickt Inhalte an Dritte — beides läuft wahlweise gegen einen lokalen Modell-Server.
Kann ich PullMD mit mehreren Nutzern betreiben?
Ja. Drei Auth-Modi: offen (Standard), Einzel-Admin fürs Homelab und Multi-User mit Registrierung und getrennten Daten pro Nutzer. API-Keys werden als SHA-256-Hash gespeichert, Passwörter mit Argon2id, und für claude.ai gibt es einen vollständigen OAuth-2.1-Flow.
Was bedeutet die AGPL-Lizenz für mich?
Nutzen, selbst hosten und verändern ist frei. Die eine Pflicht: Wer eine veränderte Version als Netzwerk-Dienst betreibt, muss deren Quellcode den Nutzern dieses Dienstes zugänglich machen. Wer eine unveränderte Instanz privat oder intern betreibt, hat keine zusätzlichen Pflichten.
Selbst hosten?
Fertige Multi-Arch-Images liegen auf Docker Hub, keine .env nötig. Repository und Dokumentation auf GitHub.
Auf GitHub ansehen ↗