Publishing to Medium Without APIs Using Chrome Extensions
Learn how to build a zero-API publishing extension for platforms with deprecated write APIs by leveraging active browser sessions and contenteditable DOM injection.
Table of Contents7 sections

When publishing platforms deprecate their developer APIs, automated syndication pipelines break. Technical bloggers and content engineers writing in local Markdown editors or static site generators are forced to manually copy and paste articles, re-format code blocks, re-upload inline graphics, and re-enter canonical URLs. Existing automation workarounds often rely on headless browser runners like Puppeteer or Playwright operating inside continuous integration servers. These headless runners require storing plaintext user credentials or session cookies on remote machines, which frequently trigger bot detection mechanisms or two factor authentication challenges. For a related implementation, see Automated Content Syndication Canonical Seo Protection.
This article examines an alternative architectural pattern that bypasses server-side bot detection entirely. By building a Manifest V3 Chrome extension that operates directly inside the user’s authentic, already-authenticated browser session, developers can programmatically transfer formatted content into modern web editors without maintaining remote servers or storing private credentials.
The Session-Native Alternative
Traditional server-driven automation treats the web as an API endpoint, attempting to simulate user actions from headless contexts. Platforms counter these headless instances with advanced fingerprinting, IP reputation scoring, and behavior analysis. When an automation script attempts to log in programmatically, it often encounters account lockouts or CAPTCHA challenges.
An extension-based approach inverts this model. The user is already logged into their publishing platform within their everyday browser. The extension injects scripts directly into the active tab where a valid session already exists. Because the request originates from the legitimate browser instance with active cookies and local storage intact, the platform perceives the action as standard user behavior. This eliminates the need for headless runners, password storage, and remote infrastructure while keeping execution entirely client-side.
The ContentEditable Challenge
Injecting content into modern web applications presents technical hurdles because platforms like Medium rely on rich text frameworks such as Draft.js, Slate, or ProseMirror. These frameworks maintain an internal JavaScript state model that governs the DOM, rather than treating the DOM as the source of truth. For a related implementation, see Automating Medium Draft Workflows.
If an extension attempts to update the editor by directly modifying .innerHTML or setting element.textContent, the underlying framework remains unaware of the change. The user interface may appear updated briefly, but the moment the user types a character or clicks save, the framework flushes its internal model over the modified DOM, erasing the injected text. Furthermore, direct mutations bypass the editor transaction history, breaking undo and redo stacks.
Synthetic Events and Clipboard Injection
To update stateful rich text editors reliably, automation scripts must interact with the browser event lifecycle in a manner that simulates genuine user input. Modern editors listen for input events and clipboard transactions to update their internal model.
Below is an implementation pattern demonstrating how to locate the target editor container and dispatch a synthetic input transaction using execCommand combined with proper event dispatching.
async function injectContentToEditor(htmlContent) {
const editorSelector = '[contenteditable="true"]';
const editor = document.querySelector(editorSelector);
if (!editor) {
throw new Error('Target contenteditable container not found');
}
editor.focus();
// Create a selection inside the editor
const selection = window.getSelection();
const range = document.createRange();
range.selectNodeContents(editor);
selection.removeAllRanges();
selection.addRange(range);
// Execute native insert command to preserve editor state model
const success = document.execCommand('insertHTML', false, htmlContent);
if (!success) {
// Fallback to synthetic input event dispatch
const dataTransfer = new DataTransfer();
dataTransfer.setData('text/html', htmlContent);
const inputEvent = new InputEvent('beforeinput', {
bubbles: true,
cancelable: true,
inputType: 'insertFromPaste',
dataTransfer: dataTransfer
});
editor.dispatchEvent(inputEvent);
}
}
This approach forces the framework to process the inserted HTML through its standard sanitization and model-update pipelines, preserving formatting for code blocks, lists, and inline styles.
Preserving Canonical Attribution
Syndicating content from a primary personal blog or documentation site to external publishing platforms introduces duplicate content risks for search engine optimization. Search engines require a clear signal indicating which URL represents the original source of truth.
An automated publishing extension should handle canonical attribution programmatically. During the payload transformation phase, the extension extracts the canonical URL of the source article and injects the corresponding metadata or footer attribution before finalizing the draft state. While platforms handle canonical links through their internal settings menus rather than direct DOM tag injection, automating the insertion of source attribution text at the end of the document body protects original domain authority and ensures readers can trace back to the primary publication.
Privacy by Design
Client-side extension architectures remove privacy liabilities common in cloud-based publishing tools. Because all article parsing, Markdown transformation, and DOM injection happen locally inside the browser, no article content or session identifiers ever traverse a third-party server. Developers maintain absolute ownership of their publishing workflow without relying on paid middleware, external databases, or analytics trackers.
Conclusion
When platform maintainers deprecate developer APIs, developers can maintain automated publishing workflows by shifting execution to the client layer. By combining Manifest V3 extensions, active browser sessions, and event-aware DOM injection, it is possible to transfer structured content into stateful editors securely and reliably without resorting to fragile headless servers or storing plaintext credentials.
Continue Exploring
You Might Also Like

Build a Zero-Drift Web Timer
Learn how to build an accurate web countdown timer using monotonic timestamps, Web Workers, visibility detection, and Web Audio synthesis.

Building a Floating Mini-Timer with Document PiP
Learn how to build a zero-drift always-on-top web timer using the modern Document Picture-in-Picture API, complete with scoped styles, keyboard controls, and progressive enhancement.

Stock Photos for Technical Articles
Learn how an editorial pipeline finds relevant stock photos for abstract software engineering topics by translating technical jargon into searchable visual queries.