Repository navigation
Embedding
This page covers the ways to put draw.io inside another application: the editor in embed mode, controlled with postMessage; the viewer library, which renders diagrams in your own page; and lightbox URLs. It is for developers integrating draw.io into a web app, CMS or tool. To show editable diagrams in GitHub READMEs and wikis, see Embed diagrams.
| You want to | Use | Runs in |
|---|---|---|
| Let users create and edit diagrams that your app stores | Embed mode | An iframe or popup with embed.diagrams.net or your own instance |
| Show diagrams read-only, with zoom, layers, pages and links | The viewer | Your page (viewer-static.min.js) |
| Link to a diagram or show it in an iframe without code | Lightbox URLs | viewer.diagrams.net |
| Show a static picture that can still be edited later | PNG or SVG with the diagram embedded (Embed diagrams, File format) | Anywhere images work |
In embed mode the editor has no storage of its own: your application passes the diagram in, and the editor hands it back when the user saves. The protocol is implemented in EditorUi.prototype.installMessageHandler (diagramly/EditorUi.js); the full reference of messages and options is embed-mode on drawio.com, and jgraph/drawio-integration has complete examples (a reusable diagram-editor.js wrapper, inline editing, local storage, WebDAV).
sequenceDiagram
participant H as Host page
participant E as Editor (iframe)
H->>E: load https://embed.diagrams.net/?embed=1&proto=json
E-->>H: {event: 'init'}
H->>E: {action: 'load', xml: '...'}
E-->>H: {event: 'load', ...}
Note over E: user edits
E-->>H: {event: 'autosave', xml} (if autosave: 1)
E-->>H: {event: 'save', xml, exit}
E-->>H: {event: 'exit', modified}
H->>E: remove the iframe
Use embed.diagrams.net for embed mode; app.diagrams.net shows a warning banner when it is opened with embed=1. The editor waits for its plugins before it sends init (see Plugins).
This page opens the editor in an iframe, loads a diagram, keeps the saved XML and closes the editor on Save & Exit or Exit:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>draw.io embed example</title>
<style>
iframe { position: fixed; inset: 0; width: 100%; height: 100%; border: 0; }
</style>
</head>
<body>
<button id="edit">Edit diagram</button>
<pre id="saved"></pre>
<script>
var editorOrigin = 'https://embed.diagrams.net';
var diagramXml = '<mxGraphModel><root><mxCell id="0"/><mxCell id="1" parent="0"/>' +
'<mxCell id="2" value="Hello" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">' +
'<mxGeometry x="40" y="40" width="120" height="60" as="geometry"/></mxCell>' +
'</root></mxGraphModel>';
var iframe = null;
function receive(evt)
{
// Only accept messages from the editor frame created below
if (iframe == null || evt.origin !== editorOrigin ||
evt.source !== iframe.contentWindow || typeof evt.data !== 'string')
{
return;
}
var msg = JSON.parse(evt.data);
if (msg.event == 'init')
{
iframe.contentWindow.postMessage(JSON.stringify({action: 'load',
xml: diagramXml, autosave: 0, title: 'example.drawio'}), editorOrigin);
}
else if (msg.event == 'save')
{
diagramXml = msg.xml;
document.getElementById('saved').textContent = diagramXml;
if (msg.exit)
{
close();
}
}
else if (msg.event == 'exit')
{
close();
}
}
function close()
{
window.removeEventListener('message', receive);
iframe.parentNode.removeChild(iframe);
iframe = null;
}
document.getElementById('edit').addEventListener('click', function()
{
if (iframe == null)
{
window.addEventListener('message', receive);
iframe = document.createElement('iframe');
iframe.setAttribute('src', editorOrigin +
'/?embed=1&proto=json&spin=1&saveAndExit=1&noSaveBtn=1');
document.body.appendChild(iframe);
}
});
</script>
</body>
</html>saveAndExit=1&noSaveBtn=1 shows Save & Exit and Exit only, so every save closes the editor. The saved xml is a complete, uncompressed <mxfile> (as in a .drawio file, see File format) that you can pass to load again. The same flow works with window.open instead of an iframe; the editor then talks to window.opener.
| Parameter | Effect |
|---|---|
embed=1 |
Turns on embed mode |
proto=json |
JSON messages as described here (without it, the editor posts the plain string ready and receives raw XML) |
spin=1 |
Shows a spinner until the diagram is loaded |
configure=1 |
Sends {event: 'configure'} first and waits for {action: 'configure', config: {...}} before it starts; the config object is the editor configuration
|
saveAndExit, noSaveBtn, noExitBtn
|
Choose the buttons (also settable in the load message) |
modified, keepmodified
|
Control the modified status text |
p |
Loads plugins by registry id |
ui, lang, dark
|
Theme, language and dark mode, as in the normal editor |
All URL parameters of the editor apply; see supported URL parameters.
| Direction | Message | Purpose |
|---|---|---|
| Editor to host | init |
Ready for load
|
| Host to editor | load |
xml (or xmlpng, or a descriptor), and options such as autosave: 1, title, modified, saveAndExit, noSaveBtn, noExitBtn, dark, rough
|
| Editor to host | load |
Sent after the diagram is loaded, with its bounds and scale |
| Editor to host | save |
The user saved: xml, and exit: true for Save & Exit
|
| Editor to host | autosave |
After each change if the load message had autosave: 1
|
| Editor to host | exit |
The user closed the editor; modified tells whether there were unsaved changes |
| Host to editor | export |
Requests format png, xmlpng, svg, xmlsvg, html, html2, xml or json; answered with an export event that has data (a data URI or text) and xml
|
| Host to editor |
merge, patch, getDiff, template, dialog, prompt, status, spinner, layout, exit, ... |
Further actions, see the reference |
The xml of a load message may be plain XML, compressed XML, a PNG data URI with an embedded diagram, an SVG data URI (data:image/svg+xml;base64, or ;utf8,) or a URI-encoded string; the editor extracts the diagram from each (extractDiagramXml in installMessageHandler). An empty string opens a blank diagram.
Embed mode works the same on a self-hosted instance (see Self-hosting): point the iframe at https://drawio.example.com/?embed=1&proto=json and use that origin in your origin check. Configure the instance as usual in PreConfig.js, or per embedding with configure=1. If your server sends X-Frame-Options or a frame-ancestors policy, it must allow the host page. Add your own plugins to the iframe URL with p after adding them to App.pluginRegistry in a fork, or load them for every page of the instance from PostConfig.js (see Plugins).
embedInline=1 is a variant for editing a diagram in place inside the host page: it implies embed=1, proto=json and the sketch theme, disables plugins, and sends the diagram back as an SVG export event when the user leaves the editor. See the inline example in jgraph/drawio-integration.
The viewer renders diagrams in your own page, read-only, with optional toolbar, layers, tags, pages, links, collapse and expand, and a lightbox for the full-size view. It is GraphViewer.js plus the core graph code, built into two bundles (see Building):
| File | Contents |
|---|---|
js/viewer-static.min.js |
The viewer and all JavaScript shapes; no code is evaluated at run time. The HTML export of the editor references this file. |
js/viewer.min.js |
Smaller: JavaScript shape files are loaded on demand from SHAPES_PATH
|
Both are served from https://viewer.diagrams.net/js/ and are in src/main/webapp/js/ of this repository. Unless you set them before the script loads, the bundles fetch their resources from viewer.diagrams.net: STENCIL_PATH, SHAPES_PATH, STYLE_PATH, GRAPH_IMAGE_PATH, mxImageBasePath, mxBasePath, DRAW_MATH_URL and PROXY_URL default to https://viewer.diagrams.net/.... The committed bundles load stencil XML from STENCIL_PATH when a diagram uses a stencil, and this repository has no stencil XML; a bundle rebuilt from this repository includes stencils.min.js instead. To serve the viewer entirely from your own host, see Self-hosting.
<div class="mxgraph" style="max-width:100%;border:1px solid transparent;"
data-mxgraph='{"highlight":"#0000ff","nav":true,"resize":true,"toolbar":"zoom layers lightbox","xml":"<mxGraphModel><root><mxCell id=\"0\"/><mxCell id=\"1\" parent=\"0\"/><mxCell id=\"2\" value=\"Client\" style=\"rounded=1;whiteSpace=wrap;html=1;\" vertex=\"1\" parent=\"1\"><mxGeometry x=\"20\" y=\"20\" width=\"120\" height=\"60\" as=\"geometry\"/></mxCell></root></mxGraphModel>"}'></div>
<script src="https://viewer.diagrams.net/js/viewer-static.min.js"></script>When the script runs, it calls GraphViewer.processElements(), which turns every element with the class mxgraph into a viewer, reading the JSON in data-mxgraph. Put the script after the elements. File > Embed > HTML in the editor generates this markup (with the attribute HTML-escaped, which is the safer form when the XML contains quotes or &).
If window.onDrawioViewerLoad is defined when the bundle loads, the bundle calls it instead of processElements, so you decide when and what to render:
<div id="diagram"></div>
<script>
window.onDrawioViewerLoad = function()
{
var xml = '<mxGraphModel><root><mxCell id="0"/><mxCell id="1" parent="0"/>' +
'<mxCell id="2" value="Hello" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">' +
'<mxGeometry x="20" y="20" width="120" height="60" as="geometry"/></mxCell></root></mxGraphModel>';
var div = document.getElementById('diagram');
div.setAttribute('data-mxgraph', JSON.stringify({xml: xml, toolbar: 'zoom', border: 10}));
GraphViewer.createViewerForElement(div, function(viewer)
{
// viewer is a GraphViewer, viewer.graph the Graph
});
};
</script>
<script src="https://viewer.diagrams.net/js/viewer-static.min.js"></script>GraphViewer.processElements(classname) processes all elements with a class (default mxgraph), GraphViewer.createViewerForElement(element, callback) one element, and new GraphViewer(container, xmlNode, graphConfig) creates a viewer from a parsed XML node. Both examples on this page were run against the current viewer.
The JSON in data-mxgraph (the graphConfig) accepts these keys, read in GraphViewer.prototype.init and related functions:
| Key | Meaning |
|---|---|
xml |
The diagram: an <mxfile>, <mxGraphModel>, or the content of an SVG or HTML export |
url |
Load the diagram from a URL instead (a plain XMLHttpRequest, so the server must allow CORS); takes precedence over xml
|
toolbar |
Space-separated buttons: pages, zoom, layers, tags, lightbox, plus your own keys defined in toolbar-buttons
|
toolbar-position, toolbar-nohide
|
top (default), inline or bottom; true keeps the toolbar visible |
zoom, border, center
|
Initial scale (default 1), padding in pixels (default 8), centring |
auto-fit, allow-zoom-in, allow-zoom-out, max-height, resize, responsive
|
Sizing behaviour |
page, pageId
|
Initial page by index or id |
layers, layerIds
|
Visible layers by index (space-separated) or id |
hiddenTags |
Tags to hide, per page |
nav |
Collapse and expand of containers |
highlight |
Colour of the hover highlight on cells with links |
target |
self or blank for links |
lightbox, edit, editable
|
false disables the lightbox, open opens it in a new window; the Edit link in the lightbox (_blank opens a copy in the editor) |
title |
Title in the toolbar |
dark-mode |
dark, auto or light (default) |
show-link-icons, show-tooltip-icons, show-note-icons
|
Icons on cells with links, tooltips or notes |
move |
Collapse and expand move the neighbouring cells |
The descriptions for users are on drawio.com. GraphViewer.prototype.* defaults (for example GraphViewer.prototype.lightboxZIndex) can be changed before the viewers are created.
viewer.diagrams.net is the editor in lightbox mode (the host name implies lightbox=1, see Init.js); on app.diagrams.net or your own instance, add lightbox=1. The diagram goes into the hash:
| Hash | Content |
|---|---|
#U<url> |
The URI-encoded URL of a diagram file (.drawio, .xml, or a PNG or SVG with an embedded diagram). The editor fetches it directly from its own origin and known CORS-enabled hosts such as raw.githubusercontent.com, and through its proxy (PROXY_URL) otherwise. |
#R<data> |
The URI-encoded diagram itself, plain or compressed with Graph.compress; this is what File > Publish > Link produces for local files |
#G, #W, #H, ... |
Files in cloud storage, see supported location hash properties |
https://viewer.diagrams.net/?highlight=0000ff&nav=1&title=schema.png#Uhttps%3A%2F%2Fraw.githubusercontent.com%2Fwiki%2Fjgraph%2Fdrawio%2Fimages%2Fschema.png
Other useful parameters are edit=_blank (an Edit button that opens a copy in the editor), layers=1, page-id, target and tags (supported URL parameters). The same URL in an <iframe> embeds the lightbox in a page; File > Embed > IFrame generates the markup.
-
Check origins in both directions. The editor only accepts messages from the window that opened or contains it (
evt.sourceis compared withwindow.openerorwindow.parent). Your page must checkevent.originandevent.sourceas in the example, and should post to the editor with its exact origin rather than*. -
Treat what comes back as untrusted. The
xmland exporteddatacontain whatever the user (or the diagram they loaded) put in it. draw.io sanitises labels when it renders them, in the editor and in the viewer, but your application must not insert returned XML or SVG markup into its own DOM withinnerHTML; show SVG exports through an<img>element or render the XML with the viewer. Never put secrets into a diagram you hand to the editor. -
Sandboxing. The load and save flow above works in an iframe with
sandbox="allow-scripts allow-same-origin"(tested);allow-same-originis needed for the editor's local storage. Addallow-popups,allow-downloadsorallow-modalsonly for the features that need them (opening links, downloads, printing). -
The viewer runs in your page. Loading
viewer-static.min.jsfrom viewer.diagrams.net executes that script with your page's privileges; self-host the bundle if that is not acceptable. Diagram content is sanitised by the viewer, and links are checked withGraph.sanitizeLink, which rejectsjavascript:URLs.
More in Security.
Describes the dev branch of jgraph/drawio as of release 32.3.0 (October 2026). Internal JavaScript APIs change between releases; check the code of the version you use. · Questions: Discussions · Bugs: Issues · Vulnerabilities: report privately · User docs: drawio.com/docs
Get started
Concepts
Guides
- Self-hosting
- Configuration
- Storage backends
- OneDrive app registration
- Embedding
- Diagrams in GitHub
- Plugins
- Extending the editor
- Shapes and stencils
- Import and export
- Desktop app
- Internationalization
Reference
Project
Elsewhere