Repository navigation
Import and Export
Every import and export format of the editor, the function that implements it, and whether it runs in the browser or needs a server. For developers who self-host (and must know what leaves the browser), debug an export, or call the conversions from their own code. Command-line export is part of the desktop app, see Desktop app.
Function names refer to js/diagramly/EditorUi.js and js/diagramly/Editor.js unless another file is named.
| Format | Import | Export | Runs |
|---|---|---|---|
.drawio / .xml (mxfile, mxGraphModel, compressed or not) |
importXml, openLocalFile
|
getFileData |
Browser |
| PNG / SVG / PDF with an embedded diagram |
Editor.extractGraphModelFromPng, Editor.extractGraphModel, Editor.extractGraphModelFromPdf
|
Editor.writeGraphModelToPng, exportSvg, PDF via the export service |
Browser. PDF with an embedded copy needs an export service. |
| PNG, JPEG, WebP | as images (importFiles) |
exportImage via Editor.prototype.exportToCanvas
|
Browser. PNG and JPEG can also use the export service. |
| SVG | as an image, or as a diagram if it has a content attribute |
exportSvg via Graph.prototype.getSvg
|
Browser |
| only PDFs with an embedded diagram | print dialog, or the export service | Browser print, or a server | |
| HTML | HTML containing a div.mxgraph
|
createHtml |
Browser. The exported page loads the viewer script. |
URL (#R link) |
App.prototype.loadFile |
createLink |
Browser |
| JSON (structure only) | none | createJsonForExport |
Browser |
| Animated GIF, MP4 | none |
showAnimatedGifExportDialog (js/diagramly/gif/) |
Browser |
Visio .vsdx, .vssx, .vstx
|
importVisio → doImportVisio (vsdx/importer.js) |
not in this repository | Browser |
Visio .vsd, .vss, .vst (binary) |
importVisio → convertBinaryVisio
|
none | Browser if the DrawioVsd converter is loaded, otherwise VSS_CONVERT_URL
|
Visio .vdx, .vsx (XML 2003-2010) |
importVisio |
none | Server only (VSS_CONVERT_URL) |
Gliffy (.gliffy JSON or zip) |
importGliffy |
none | Browser (js/gliffy/drawio-gliffy.min.js) |
| Lucidchart (JSON state, clipboard) |
convertLucidChart → LucidImporter (Extensions.js) |
none | Browser |
| Mermaid | parseMermaidDiagram |
Mermaid source kept in the cell | Browser (bundle in extensions.min.js) |
| PlantUML | parsePlantUmlDiagram |
PlantUML source kept in the cell | Browser (js/plantuml/drawio-plantuml.min.js) |
CSV with # configuration lines |
importCsv → doImportCsv
|
none | Browser |
| GraphML (yEd) |
importGraphML → mxGraphMlCodec (graphml/) |
none | Browser |
| Miro (clipboard JSON) |
MiroImporter.importMiroJson (miro/) |
none | Browser, paste only |
Plain text, SQL CREATE TABLE
|
ParseDialog (Dialogs.js) |
none | Browser |
Libraries (<mxlibrary>) |
loadLibrary |
saveLibrary |
Browser |
The importers for Visio, Lucidchart, GraphML, Miro and Mermaid are compiled into js/extensions.min.js (the extensions part of the app target in etc/build/build.xml, see Building). PlantUML and Gliffy are separate bundles that are loaded on demand. Like the Mermaid, layout and routing bundles, they are built outside this repository and committed as minified files.
Servers are involved in only four cases:
- PDF export with an export service configured, and the server-side PNG/JPEG fallback;
- Visio formats the browser converter cannot read (
VSS_CONVERT_URL); -
File > Import from > URL, which fetches through
PROXY_URL(the ProxyServlet at/proxy, which answers 404 unless the server environment setsENABLE_DRAWIO_PROXY=1); - remote images and fonts in an export:
Editor.prototype.createImageUrlConverterandmapFontUrlroute other-origin URLs through the same proxy.
The menu exportAs in Menus.js adds these actions:
| Item | Action | Shown when |
|---|---|---|
| PNG, JPEG, WebP |
exportPng, exportJpg, exportWebp
|
editor.isExportToCanvas(). JPEG and WebP also need Editor.jpgSupported / Editor.webpSupported. Without canvas export, PNG and JPEG are offered if isRemoteExportEnabled(). |
| Animation | exportAnimatedGif |
canvas export |
| SVG | exportSvg |
always |
exportPdf |
always (not in iOS standalone mode when an export service is used) | |
| VSDX | exportVsdx |
vsdxExportEnabled(), which is false in the app built from this repository |
| HTML, XML, URL, JSON |
exportHtml, exportXml, exportUrl (if Editor.enableExportUrl), exportJson
|
always |
| Advanced... |
export → ExportDialog
|
when online |
File > Embed (createEmbedImage, createEmbedSvg, createHtml, createLink) uses the same functions. Copy as image and Copy as SVG use copyImage and copySvg.
Graph.prototype.getSvg (grapheditor/Graph.js, extended in diagramly/Editor.js for math and themes) creates an mxSvgCanvas2D and paints every cell state with mxImageExport, the same shapes as on screen. HTML labels become <foreignObject> elements. addForeignObjectWarning adds a <switch> fallback for viewers without foreignObject support. EditorUi.prototype.exportSvg adds the options of the export dialog: embedded images and fonts, links, theme, and the diagram copy in the content attribute. As the README says, SVG export is meant for embedding in web pages, not for editing in other tools.
The raster formats are rendered from the SVG:
-
Editor.prototype.exportToCanvascallsgetSvgand inlines images withconvertImages. It embeds fonts (embedExtFonts), draws the SVG data URI into a<canvas>, and passes the canvas on. -
EditorUi.prototype.exportImage→saveCanvas→createImageDataUri(canvas.toDataURL, plus the diagram chunk and DPI for PNG) →saveData, which downloads a Blob.
Editor.prototype.isExportToCanvas() is true when Editor.useCanvasForExport is. At start-up, the editor sets that flag by drawing a test SVG with a foreignObject to a canvas. If the browser cannot do that, PNG and JPEG are only offered through the export service. Editor.prototype.getMaxCanvasScale limits the canvas to 16384 pixels per side (8192 in Firefox) by reducing the scale.
"Include a copy of my diagram" stores the mxfile in the image:
-
PNG:
Editor.writeGraphModelToPng(data, 'tEXt', 'mxfile', encodeURIComponent(xml))inserts atEXtchunk before the firstIDAT.Editor.extractGraphModelFromPng(grapheditor/Editor.js) readstEXtandzTXtchunks with the keywordmxfileormxGraphModel. Files named.drawio.pngare saved this way automatically (getEmbeddedPng). -
SVG: the
contentattribute of the root<svg>holds the mxfile, as plain, URI-encoded or base64 data.Editor.extractGraphModelreads it..drawio.svgfiles usegetEmbeddedSvg.
The details are in File format.
PDF has two paths, chosen by EditorUi.prototype.isPrintPdfExport(), which is printPdfExport || !isRemoteExportEnabled():
-
Print dialog (the default for builds from this repository). The public PreConfig.js sets
window.EXPORT_URL = null, soisRemoteExportEnabled()is false. Export as > PDF opens the print dialog (showPrintDialog→PrintDialog→EditorUi.prototype.print), and the browser saves the PDF. No diagram data leaves the browser, but the PDF cannot contain a copy of the diagram. This is the behaviour described for the Docker image in Run a draw.io server with Docker. -
Export service. If
EXPORT_URLis an absolutehttp(s)URL or starts with/,downloadFile('pdf', ...)builds the request indownloadRequestBuilderand POSTs the diagram XML and options to it. Options include format, page range, scale, border, crop, transparent background and embedded copy. The service renders the diagram in a headless browser and returns the file. Requests are refused in the browser aboveMAX_AREA(15000 × 15000) orMAX_REQUEST_SIZE(10 MB).
EXPORT_URL is set only in PreConfig.js, never from a URL parameter. A link must not be able to redirect the diagram to someone else's server (advisory GHSA-ff67-v9r9-6877).
This repository does not contain an export service. It contains the parts one uses:
| File | Role |
|---|---|
| export3.html, js/export-init.js, js/export.js | The render page: loads app.min.js and extensions.min.js. The headless browser calls render(data) with xml, csv or mermaid and the options. When the page is laid out, a hidden #LoadingComplete element carries the bounds, scale and page count for the driver. The desktop app uses the same page for its PDF and command-line export. |
ExportProxyServlet.java, mapped to /export and /service/*
|
Forwards a request to the URL in the server's EXPORT_URL environment variable, so the browser can use a same-origin window.EXPORT_URL = '/export'. Responses are capped at 100 MB. |
The Node/Puppeteer reference service jgraph/draw-image-export2 is archived, and the docker-drawio README says the jgraph/export-server image has reached end of life. See Related repositories.
-
HTML:
createHtmlwrites a<div class="mxgraph" data-mxgraph="...">with the diagram and options, plus a<script>tag for the viewer:DRAWIO_VIEWER_URLif set, otherwise<DRAWIO_LIGHTBOX_URL>/js/viewer-static.min.js(defaulthttps://viewer.diagrams.net). A self-hosted deployment that must not depend on viewer.diagrams.net setsDRAWIO_VIEWER_URL. See Embed diagrams. -
XML:
downloadFile('xml')→getFileData, optionally compressed (Editor.defaultCompressed, configuration keycompressXml). -
URL:
createLinkcreates#R+encodeURIComponent(Graph.compress(xml)).Graph.compressispako.deflateRawof the URI-encoded XML, base64-encoded.#Rlinks open withApp.prototype.loadFile, see Storage backends. -
JSON:
createJsonForExport(allPages, includeData, compressed, selection)writes the pages, cells and labels as JSON, optionally with the mxfile in adatafield. There is no importer for this format.
showAnimatedGifExportDialog exports flow animations with AnimatedGifExport and step animations with AnimationExport. Output is a GIF (GifEncoder) or an MP4 (Mp4Encoder, which uses WebCodecs, gated by Mp4Encoder.isSupported()). All of it is in js/diagramly/gif/ and runs in the browser.
EditorUi.prototype.exportVisio creates a VsdxExport, a class that is not part of this repository. The VSDX menu item is hidden unless vsdxExportEnabled() returns true, and in the app built from this repository it does not. The desktop command line does not export VSDX either.
| Constant | Value | Applies to |
|---|---|---|
MAX_REQUEST_SIZE (grapheditor/Init.js) |
10 MB | Requests to the export service |
MAX_AREA (grapheditor/Init.js) |
15000 × 15000 | Diagram bounds sent to the export service |
Editor.prototype.getMaxCanvasScale |
16384 px (8192 in Firefox) | Canvas exports, by reducing the scale |
EditorUi.prototype.maxCanvasExportArea |
8192² px | PNG exports through the embed protocol |
EditorUi.prototype.maxPrintPageCount |
1000 | Print preview pages |
EditorUi.prototype.maxImageBytes |
2,000,000 | Inserted images ("image too big" above this) |
EditorUi.prototype.maxImageSize |
1200 px | Inserted images are scaled to fit (configuration maxImageSize) |
EditorUi.prototype.maxTextBytes |
500,000 | Inserted text is truncated |
An embedding application can request exports through the export action of the JSON protocol, in the formats png, xmlpng, svg, xmlsvg, html, html2, xml and json. The result comes back in an export message instead of a download. See Embedding and the embed mode reference.
| Entry | Function | Behaviour |
|---|---|---|
| File > Open, opening a file dropped on an empty diagram |
openFiles → openLocalFile
|
Replaces the current file. Detects Visio, GraphML, Gliffy, Lucidchart and libraries, and extracts the diagram from PNG and PDF. |
| File > Import from > Device |
importLocalFile(true) → importFiles
|
Adds to the current diagram |
| File > Import from > URL |
PROXY_URL + '?url=' + url → importFile
|
Adds to the current diagram |
| Drop on the canvas |
drop listener on graph.container → importFiles, or extractGraphModelFromEvent for text and HTML |
Adds at the drop position. Shift-drop, or one .drawio/.xml/Visio file dropped on a blank diagram, opens it instead. |
| Drop on the page outside the canvas |
addFileDropHandler (installed by App) |
Opens the files |
| Paste |
pasteCells → pasteXml, pasteFromClipboard
|
See below |
importFiles(files, x, y, ...) reads each File:
- SVG with an mxfile in
contentis imported as a diagram; other SVGs become image cells. - PNG with an embedded diagram is imported as a diagram; other images become image cells. Images are resized above
maxImageSize, andEditor.removeImageMetadatacan strip EXIF data. - Visio files go to
importVisio. - PDFs are read as data URLs and passed to
insertTextAt, which callsEditor.extractGraphModelFromPdf. - Everything else is read as text and passed to
importFile.
importFile(data, mimeType, ...) checks, in this order:
- a library (
<mxlibrary>, loaded withloadLibrary); - an image, or a PNG with an embedded diagram;
-
<graphml→importGraphML; - a Visio file name →
importVisio; - Gliffy data (
isGliffyData) →importGliffy; - a zip archive (
PK) →importZipFile, which takesdiagram/diagram.xmlfrom a draw.io zip or the latestversions/entry of a Gliffy archive; - anything else →
insertTextAt.
insertTextAt handles PNG, PDF and SVG data URIs. It sends draw.io XML (isCompatibleString) to importXml and Lucidchart JSON (isLucidChartData) to convertLucidChart. Other text becomes a text cell, sanitised and truncated at maxTextBytes. importXml(xml, dx, dy, crop, ...) does the actual insert: a multi-page mxfile adds pages, a single page is merged into the current page.
Paste. pasteCells recognises, in order:
- Lucidchart clipboard HTML (
data-lucid-type="application/vnd.lucid.chart.objects") →convertLucidChart; - draw.io XML, also URI-encoded;
- Miro clipboard JSON (starting with
{"isProtected":) →MiroImporter; - files on the clipboard →
importFiles.
Anything else goes to pasteXml. The asynchronous Clipboard API path is pasteFromClipboard → readGraphModelFromClipboard.
importVisio(file, done, error, filename) loads extensions.min.js if needed:
-
.vsdx,.vssxand.vstxare unzipped (JSZip) and converted in the browser bymxVsdxCodec(diagrams) ormxVssxCodec(stencils, which become a library), in vsdx/importer.js. Embedded EMF images go throughemfToSvg(emf/emf-svg.js), BMP images throughBmpDecoder(vsdx/bmpDecoder.js). -
.vsd,.vssand.vstare converted in the browser byconvertBinaryVisiowhen theDrawioVsdconverter (js/vsd/drawio-vsd.min.js, appended toextensions.min.jsby the build) is loaded and can read the file. - Otherwise, and for
.vdxand.vsx(isRemoteVisioFormat), the file is POSTed toVSS_CONVERT_URL. That defaults to a conversion service on convert.diagrams.net (diagramly/Init.js) and is skipped when the editor is offline.
Init.js sets the default with ||, so a null in PreConfig.js does not disable it. A deployment that must never send files there sets window.VSS_CONVERT_URL = null; in PostConfig.js, which loads after the app, or runs with offline=1.
vsdxImporter.html with js/vsdxImporter.js is a headless page around importVisio. The desktop command line uses it for Visio input.
-
Gliffy:
importGliffy→loadGliffy(loadsjs/gliffy/drawio-gliffy.min.js) →mxGliffyToDrawio.convert(data). It accepts Gliffy JSON ("contentType":"application/gliffy+json") and Gliffy zip archives. -
Lucidchart:
convertLucidChart→LucidImporter.importState, in Extensions.js. The input is Lucidchart's JSON document state (isLucidChartData), typically from the clipboard. It is not a.lucidfile.
End-user steps: Lucidchart import, Gliffy import, import formats.
Arrange > Insert > Advanced (and Insert > Mermaid) open ParseDialog (Dialogs.js). Its types are:
| Type | Converter |
|---|---|
mermaid (editable shapes), mermaidImage
|
parseMermaidDiagram / parseMermaidImage, using mxMermaidToDrawio from the Mermaid bundle in extensions.min.js. Available when EditorUi.isMermaidSupported(), which needs structuredClone. |
plantUmlDiagram, plantUmlImage
|
parsePlantUmlDiagram / parsePlantUmlImage, using mxPlantUmlToDrawio from js/plantuml/drawio-plantuml.min.js
|
list |
Class-like blocks of text become list shapes |
diagram, circle, horizontalFlow, verticalFlow
|
One edge per line, a->b or a->label->b, laid out with the chosen layout. Lines starting with ; are ignored. |
table |
CREATE TABLE statements become table shapes |
Mermaid and PlantUML run entirely in the browser; no rendering server is involved. The generated cells keep the source in the mermaidData or plantUmlData attribute, so the diagram can be edited and regenerated. User documentation: Mermaid, PlantUML, from text.
Arrange > Insert > Advanced > CSV → showImportCsvDialog → importCsv → doImportCsv. The input is CSV data preceded by # lines that configure labels, styles, connections, placement and layout. doImportCsv creates or, with an identity column, updates the cells inside one model transaction, so one undo reverts the import. An org-chart layout loads its scripts (loadOrgChartLayouts) first. The format is documented at Insert from CSV. The same code runs headless in export.js when an export request carries csv.
-
GraphML (yEd):
importGraphML→mxGraphMlCodec.decode(graphml/mxGraphMlCodec.js). Import only. -
Miro: clipboard JSON copied from a Miro board, converted by
MiroImporter.importMiroJson(miro/MiroImporter.js). Paste only. -
Libraries:
<mxlibrary>files open as a sidebar library (loadLibrary), not as a diagram. See Shapes and stencils.
The plugins import.js (p=import, Freemind) and sql.js (p=sql) add more importers, see Plugins.
- File format: mxfile, compression, embedded diagrams in PNG/SVG
- Desktop app: command-line export
- Embedding and Embed diagrams
- Storage backends
-
Self-hosting and Configuration:
EXPORT_URL,VSS_CONVERT_URL,PreConfig.js/PostConfig.js - 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