Bis hierher hat die Automatisierung nichts veröffentlicht. Sie hat eingesammelt, Texte erzeugt und eine Warteschlange gefüllt. Dieser Teil handelt vom letzten Meter – und der hat es in sich, weil Facebook und Instagram trotz gemeinsamer API sehr unterschiedlich funktionieren.
Das Bildformat, an dem alles gescheitert wäre
Der erste Fund kam, bevor überhaupt eine Zeile Workflow stand. Ich hatte mir angesehen, welche Bilder der Blog liefert:
https://…/uploads/2026/08/erste-nacht-draussen-anfaenger.webp
WebP. Und das ist ein Problem, denn:
- Facebook akzeptiert bei Foto-Uploads JPEG, PNG, GIF, BMP und TIFF. WebP steht nicht auf der Liste.
- Instagram verlangt beim Content Publishing eine öffentlich erreichbare JPEG-URL.
Ohne Umwandlung wäre jeder einzelne Post gescheitert – und zwar mit einer Fehlermeldung über Medientypen, die einen erst mal in die falsche Richtung schickt.
Viele WordPress-Installationen liefern heute WebP aus, teils über ein Optimierungs-Plugin, teils über den Server. Es lohnt sich, das vor dem Bauen zu prüfen: Beitragsbild-URL aufrufen und auf die Endung schauen. Zwei Minuten, die einen Nachmittag sparen können.
Die Lösung ist in n8n ein einzelner Node. Der Edit-Image-Node kann nicht nur zuschneiden, sondern über seine Optionen auch das Ausgabeformat setzen:
- Operation:
resize, 1440 × 1440, Modus nur wenn größer - Optionen: Format
jpeg, Qualität 88, Dateinamesocial.jpg
Die Größenbegrenzung ist Nebensache – entscheidend ist der Formatwechsel. Dass er als Option eines Resize-Vorgangs versteckt ist, macht ihn leicht übersehbar.
Facebook: erfreulich unspektakulär
Der Facebook-Teil ist in einem Node erledigt. Der Facebook-Graph-API-Node bekommt:
- Methode
POST - Node: die Seiten-ID
- Edge:
photos - Binärdaten senden: an, Feld
data - Query-Parameter:
messagemit dem Text
Und das war es. Der /photos-Endpunkt nimmt Binärdaten direkt entgegen – kein Zwischenspeichern, keine öffentliche URL nötig. Der Text kommt als message mit, der Link steht darin und Facebook baut daraus die Vorschau.
Die Antwort enthält zwei IDs:
{
"id": "122176508450951891",
"post_id": "740198199181160_122176508474951891"
}
Die post_id mit dem Unterstrich ist die, die man aufheben will – mit ihr lässt sich der Beitrag später wiederfinden. Sie landet bei mir in der Warteschlangenzeile.
Bildpost oder Linkvorschau?
An dieser Stelle gibt es eine Entscheidung, die man leicht übergeht. Facebook kennt zwei Wege, einen Beitrag mit Link zu posten.
Der eine ist /feed mit dem Parameter link. Facebook holt sich dann selbst die Open-Graph-Daten der Seite und baut die bekannte Vorschaukarte mit Titel, Beschreibung und Bild. Der Vorteil: Die ganze Karte ist klickbar, und man muss sich um das Bild nicht kümmern.
Der andere ist /photos mit einem eigenen Bild. Der Link steht dann im Text. Etwas mehr Aufwand, weil man das Bild selbst liefern muss.
Ich habe mich für /photos entschieden, aus zwei Gründen. Erstens ist die Darstellung berechenbar: Bei der Vorschaukarte hängt das Ergebnis davon ab, was Facebook aus den Open-Graph-Tags macht und wann es die Seite zuletzt abgerufen hat – ändert man das Beitragsbild, kann tagelang das alte in der Vorschau kleben. Zweitens ist es dieselbe Bildstrecke wie für Instagram; ein Weg statt zweier.
Der Nachteil: Im Foto-Post ist nur der Text klickbar, nicht das Bild. Wer auf Klicks statt auf Sichtbarkeit optimiert, sollte das gegeneinander abwägen und im Zweifel messen, statt es zu glauben.
Instagram: zwei Schritte, und der zweite fehlt oft
Instagram funktioniert grundsätzlich anders, und hier liegt ein Fehler versteckt, den ich in einer verbreiteten fertigen Vorlage gefunden habe.
Das Veröffentlichen läuft zweistufig:
POST /{ig-id}/medialegt einen Media-Container an. Er bekommt die Bild-URL und die Bildunterschrift. Zurück kommt eine Container-ID. Sichtbar ist noch nichts.POST /{ig-id}/media_publishmitcreation_id=<Container-ID>veröffentlicht ihn.
Dazwischen gehört eine kurze Wartezeit – Instagram verarbeitet den Container asynchron. Dreißig Sekunden reichen für Bilder gut aus.
Der erwähnte Fehler: Eine populäre Vorlage für genau diesen Anwendungsfall führt nur Schritt 1 aus. Sie legt den Container an, freut sich über die zurückgegebene ID – und ruft media_publish nie auf. Wer sie übernimmt, sieht einen grünen Workflow und wundert sich, warum auf Instagram nichts erscheint.
Das ist übrigens auch der Grund, warum ich Vorlagen inzwischen aufklappe, bevor ich sie einsetze. Ein Workflow, der durchläuft, ist nicht dasselbe wie ein Workflow, der funktioniert.
Der Umweg über die Mediathek
Instagram nimmt keine Binärdaten. Es will eine öffentlich erreichbare JPEG-URL. Das ist unbequem, wenn man das Bild gerade erst umgewandelt hat und es nur im Arbeitsspeicher des Workflows liegt.
Die Lösung, die ohne zusätzlichen Dienst auskommt: zurück in die WordPress-Mediathek. Ein HTTP-Request-Node lädt das JPEG über die REST-API hoch:
POST /wp-json/wp/v2/media- Authentifizierung: die vorhandene WordPress-Credential
- Header
Content-Disposition: attachment; filename="ig-<post_id>.jpg" - Body: Binärdaten
Die Antwort enthält source_url – eine öffentliche Adresse auf der eigenen Domain, die Instagram akzeptiert.
Der Preis dafür sind zusätzliche Dateien in der Mediathek. Deshalb der einheitliche Namensbaustein ig- samt Beitrags-ID: So lassen sie sich jederzeit gesammelt finden und aussortieren. Wer das lieber vermeidet, kann einen Bilderdienst dazwischenhängen – dann hängt die Automatisierung aber an einem weiteren Zugang.
Der Test, der nichts veröffentlicht
Und jetzt der Kniff, der mir einen peinlichen Testbeitrag erspart hat.
Weil Schritt 1 allein nichts Sichtbares erzeugt und der Container nach 24 Stunden von selbst verfällt, kann man die gesamte Kette prüfen, ohne zu posten:
POST /{ig-id}/media
?image_url=<JPEG-URL>
&caption=Testcontainer, wird nicht veroeffentlicht.
Kommt eine ID zurück, ist bewiesen:
- Das Token hat die Berechtigung
instagram_content_publish(wie man ein solches Token erzeugt, steht in der Token-Anleitung) - Die Konto-ID stimmt
- Die Bild-URL ist öffentlich erreichbar
- Das Format wird akzeptiert
Bei mir kam die ID 17905410990538837 zurück – und damit war klar, dass nur noch der Publish-Aufruf fehlte. Diesen Trockentest habe ich aus einem separaten Hilfsworkflow gefahren, mit dem echten Bildpfad, aber ohne die letzte Stufe.
Übertragbar: Suche bei jeder Publishing-API nach einem Zwischenschritt, der sich isoliert prüfen lässt. Bei zweistufigen Verfahren gibt es fast immer einen.
Dreißig Sekunden sind geraten
Eine Stelle in diesem Workflow ist bewusst unsauber, und ich schreibe sie lieber selbst auf, bevor sie jemand findet: die Wartezeit zwischen Container und Veröffentlichung.
Instagram verarbeitet den Container im Hintergrund. Wie lange das dauert, hängt vom Bild und von der Tageslast ab – es ist keine feste Größe. Mein Workflow wartet stur dreißig Sekunden und ruft dann media_publish auf. Das hat in allen Läufen funktioniert, aber es funktioniert nicht deshalb, weil dreißig Sekunden richtig wären. Es funktioniert, weil Bilder schnell fertig sind.
Der saubere Weg wäre, den Container abzufragen und erst zu veröffentlichen, wenn er als fertig gemeldet wird – eine kleine Schleife statt einer Zahl. Das habe ich nicht gebaut, aus einem Grund, den ich für vertretbar halte: Bei einem Post pro Slot kostet eine gescheiterte Veröffentlichung wenig, und der Eintrag bleibt in der Warteschlange stehen. Bei zwanzig Posts in Folge oder bei Videos, die deutlich länger brauchen, wäre die feste Zahl fahrlässig.
Das ist der Unterschied zwischen einer Abkürzung und einem Fehler: Eine Abkürzung kennt man, benennt man und weiß, wann sie nicht mehr trägt.
Fehlerpfade: was scheitern darf und was nicht
Ein Detail, das im Betrieb den Unterschied macht: Nicht jeder Fehler soll alles anhalten.
Bei mir sind die Fehlerbehandlungen unterschiedlich gesetzt:
Der Facebook-Node ist auf Fehlerausgang gestellt. Scheitert er, läuft die Ausführung in einen eigenen Zweig, der zwei Dinge tut: Er schreibt den Status fehler samt Meldung in die Warteschlangenzeile, und er verschickt eine E-Mail. Der Eintrag bleibt damit stehen und lässt sich später durch Zurücksetzen auf freigegeben nachholen. Nichts geht verloren.
Die Instagram-Nodes dagegen stehen auf normal weiterlaufen. Der Gedanke: Instagram ist die zusätzliche Reichweite, Facebook das Rückgrat. Wenn Instagram zickt, soll der Facebook-Post trotzdem rausgehen. Ein Instagram-Problem darf nicht den ganzen Slot blockieren.
Diese Abstufung sollte man bewusst treffen, statt überall dieselbe Einstellung zu nehmen. Die Frage lautet jedes Mal: Ist dieser Schritt für den Zweck des Durchlaufs notwendig – oder ergänzend?
Was ich bewusst nicht gebaut habe: eine automatische Wiederholung. Bei einem Berechtigungsfehler läuft die endlos, produziert Fehlermails im Minutentakt und verdeckt die eigentliche Ursache. Ein Nachholen von Hand ist hier ehrlicher – und weil der Eintrag in der Tabelle stehen bleibt, kostet es einen Klick.
Was am Ende zurückgeschrieben wird
Nach erfolgreichem Post aktualisiert der Workflow die Zeile:
statusaufgepostetgepostet_ammit dem Zeitstempelfb_post_idundig_post_idmit den Belegen
Das klingt nach Buchhaltung und ist genau das. Ohne diese Rückschreibung weiß niemand, was wirklich rausging – und der Doppel-Schutz aus Teil 3 hätte keine Grundlage.
Der erste vollständige Durchlauf
Zum Abschluss der Beleg, dass es zusammenpasst. Beitrag Mikroabenteuer lief über die ganze Strecke:
| Schritt | Ergebnis |
|---|---|
| Bild laden (WebP) | ✓ |
| Umwandlung nach JPEG | ✓ |
| Facebook-Post | ✓ Post-ID zurückgegeben |
| Upload in die Mediathek | ✓ |
| Instagram-Container | ✓ |
| 30 Sekunden warten | ✓ |
| Instagram veröffentlichen | ✓ Media-ID zurückgegeben |
| Rückschreiben in die Tabelle | ✓ |
Siebenundvierzig Sekunden von Anfang bis Ende, davon dreißig reines Warten.
Die drei Punkte zum Mitnehmen
Prüfe das Bildformat, bevor du irgendetwas baust. WebP ist auf beiden Plattformen ein Problem, und die Fehlermeldung sagt es nicht deutlich.
Bei zweistufigen APIs zähle die Schritte nach. Ein Container ist kein Beitrag. Und genau diese Lücke findet sich in fertigen Vorlagen.
Staffle die Fehlerbehandlung nach Wichtigkeit. Was ergänzend ist, darf scheitern, ohne den Rest mitzureißen. Was tragend ist, gehört in einen Fehlerzweig mit Benachrichtigung und Nachhol-Möglichkeit.
Die Serie:
- Teil 1: Warum Texten und Posten getrennt gehören
- Teil 2: Texte, die etwas sagen
- Teil 3: Die Warteschlange als Redaktionsplan
- Teil 4: Posten auf Facebook und Instagram – dieser Beitrag
- Teil 5: Altbestand nachziehen und der Betrieb



