If you've ever needed to turn a list of nodes and connections into a clean, readable diagram, the Graphviz DOT language is one of the most reliable ways to do it. It's a plain-text graph description language that lets you define nodes, edges, and their properties then renders them into visual diagrams automatically. Whether you're mapping out a software architecture, visualizing data relationships, or documenting system flows, having a solid syntax reference for DOT saves hours of trial and error.
This reference covers the core syntax rules, practical examples, common pitfalls, and tips so you can write DOT code confidently without constantly searching for answers.
What is the DOT language, and how does Graphviz use it?
DOT is a declarative language created as part of the Graphviz (Graph Visualization Software) project originally developed at AT&T Labs. You describe a graph's structure in plain text, and Graphviz tools like dot, neato, fdp, and circo render it into formats like SVG, PNG, or PDF.
A DOT file describes three main things:
- Nodes individual elements in the graph
- Edges connections between nodes
- Attributes visual and structural properties like color, shape, and label text
Because DOT files are plain text, they work well with version control systems, automated pipelines, and scripting. You can find more about the project's background in the official Graphviz documentation.
What does the basic syntax structure look like?
A DOT graph starts with either digraph for directed graphs (with arrow edges) or graph for undirected graphs (with plain lines). Everything else goes inside curly braces.
Here's the skeleton:
digraph {
A -> B
B -> C
}
For an undirected graph:
graph {
A -- B
B -- C
}
Notice the difference: -> creates a directed edge, while -- creates an undirected one. This is one of the first syntax distinctions new users encounter, and mixing them up is a common source of errors.
How do you define and label nodes?
In its simplest form, a node is just an identifier:
MyNode
You assign attributes to nodes using square brackets. The most common attribute is label:
MyNode [label="My Custom Label"]
Other frequently used node attributes include:
- shape box, ellipse, circle, diamond, plaintext, and many more
- style filled, dashed, rounded, bold
- fillcolor background fill color (requires
style=filled) - color border/outline color
- fontname font family for the label
- width / height fixed dimensions in inches
A practical example:
Database [label="User DB", shape=cylinder, style=filled, fillcolor="#4A90D9", fontcolor=white]
You can set default attributes for all nodes at once by using the node keyword with attributes in brackets:
node [shape=box, style=filled, fillcolor=lightyellow]
Every node defined after that line inherits those defaults unless overridden individually.
How do edges work in DOT syntax?
Edges connect two nodes using an operator. In a digraph, use ->. In a graph, use --.
A -> B [label="connects to"]
Edges also accept attributes in square brackets:
- label text displayed along the edge
- color line color
- style dashed, dotted, bold, solid
- arrowhead none, normal, dot, diamond, crow, and others
- arrowtail shape of the arrow at the tail end
- dir direction: forward, back, both, none
- weight influences edge length and layout priority
You can chain edges for compact notation:
A -> B -> C -> D
This is equivalent to writing three separate edge statements. If you're building more complex flows like those in architecture diagram examples, chaining keeps the code readable.
Can you set default edge attributes?
Yes. Just like nodes, edges have a global default keyword:
edge [color=gray, style=dashed, arrowhead=vee]
All edges defined after this line use those defaults unless you override them on a specific edge.
What about subgraphs and clusters?
Subgraphs group related nodes together. In Graphviz, if you name a subgraph with a prefix of cluster_, it renders as a visual box around those nodes.
digraph {
subgraph cluster_frontend {
label="Frontend"
style=filled
color=lightgrey
UI -> API_Call
}
subgraph cluster_backend {
label="Backend"
style=filled
color=lightblue
Server -> Database
}
API_Call -> Server
}
Clusters are especially useful for system and network diagrams where you need to show boundaries between components or environments. This technique appears frequently when people automate reporting with Graphviz, since the layout engine handles positioning inside and outside clusters automatically.
How do you set the overall graph attributes?
Graph-level attributes control the entire diagram's appearance. Place them at the top of the graph body, outside any subgraph.
digraph {
rankdir=LR
bgcolor=white
fontname="Arial"
label="System Architecture"
labelloc=t
fontsize=18
pad=0.5
nodesep=0.8
ranksep=1.0
}
Common graph attributes:
- rankdir direction of layout:
TB(top-bottom, default),LR(left-right),BT,RL - bgcolor background color of the entire canvas
- label title displayed on the graph
- labelloc vertical position of the label:
t(top) orb(bottom) - nodesep minimum space between nodes in the same rank
- ranksep minimum space between rank levels
- splines edge routing style:
ortho,curved,polyline,spline - concentrate merges edges that share endpoints (set to
true)
What are HTML-like labels, and when should you use them?
DOT supports HTML-like label syntax when you need formatted text inside nodes things like bold, italic, line breaks, tables, or mixed formatting within a single label.
Info [label=<
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
<TR><TD COLSPAN="2"><B>User Info</B></TD></TR>
<TR><TD>Name</TD><TD>Jane Doe</TD></TR>
<TR><TD>Role</TD><TD>Admin</TD></TR>
</TABLE>
>, shape=plaintext]
Use angle brackets < > instead of regular quotes to enable HTML label mode. This is useful for database schemas, structured data displays, and detailed component cards. Note that the syntax here is not full HTML it's a limited subset specific to Graphviz.
What common mistakes break DOT syntax?
Here are errors that trip up both beginners and experienced users:
- Mixing directed and undirected operators. Using
->in agraphblock or--in adigraphblock causes parsing errors. - Missing semicolons or braces. DOT is somewhat forgiving about whitespace and semicolons, but mismatched braces will fail silently or throw cryptic errors.
- Using reserved words as node IDs. Words like
node,edge,graph,subgraph, andstrictare reserved. Wrap them in quotes if you need them as identifiers:"node" [label="Server"]. - Forgetting to escape special characters. Characters like quotes, angle brackets, and backslashes inside labels need escaping: use
\"for quotes inside a quoted string. - Confusing attribute separators. Attributes inside brackets are separated by commas, but you can also use whitespace. Consistency matters for readability.
- Not specifying the graph type. If you start with just
{instead ofdigraph {, the parser won't know which edge operator to expect.
How do you render a DOT file into an image?
From the command line, the basic syntax is:
dot -Tpng input.dot -o output.png
Supported output formats include -Tsvg, -Tpdf, -Tjpg, and -Tps. Different layout engines suit different graph types:
- dot hierarchical/layered layouts (best for directed acyclic graphs)
- neato spring model layouts (good for undirected graphs)
- fdp force-directed placement
- circo circular layout
- twopi radial layout
If you don't have Graphviz installed locally, you can use an online DOT graph editor to write and preview your diagrams in the browser.
Quick reference: full DOT syntax example
Here's a complete, working example that combines the major syntax elements discussed above:
digraph Pipeline {
rankdir=TB
bgcolor=white
fontname="Arial"
node [shape=box, style="filled,rounded", fillcolor="#E8F4FD", fontname="Arial"]
edge [color="#555555", fontname="Arial", fontsize=10]
subgraph cluster_sources {
label="Data Sources"
style=filled
color="#F0F0F0"
CSV [label="CSV Files"]
API [label="REST API"]
}
subgraph cluster_processing {
label="Processing"
style=filled
color="#FFF3E0"
ETL [label="ETL Pipeline", fillcolor="#FFB74D"]
Validate [label="Validation", shape=diamond]
}
subgraph cluster_output {
label="Output"
style=filled
color="#E8F5E9"
DB [label="Warehouse", shape=cylinder]
Report [label="Dashboard"]
}
CSV -> ETL
API -> ETL
ETL -> Validate
Validate -> DB [label="pass"]
Validate -> ETL [label="fail", style=dashed, color=red]
DB -> Report
}
This example demonstrates directed edges, subgraph clusters, node and edge defaults, labels, shapes, colors, and feedback loops all in under 30 lines of plain text.
DOT language syntax cheat sheet
| Element | Syntax | Example |
|---|---|---|
| Directed edge | A -> B | Start -> End |
| Undirected edge | A -- B | Start -- End |
| Node with attributes | ID [attr=value] | Web [label="Web Server", shape=box] |
| Edge with attributes | A -> B [attr=value] | A -> B [label="data", style=dashed] |
| Default node attrs | node [attr=value] | node [shape=ellipse] |
| Default edge attrs | edge [attr=value] | edge [color=gray] |
| Subgraph | subgraph name { ... } | subgraph cluster_aws { ... } |
| Graph direction | rankdir=LR | Left-to-right layout |
| HTML label | label=<HTML> | label=<<B>Bold</B>> |
| Comment | // comment or / comment / | Ignored by parser |
Practical checklist before you render
- Start with
digraphorgraphpick the right one for your edge type. - Define global defaults for
node,edge, and graph-level attributes at the top. - Use meaningful node IDs (they're internal identifiers; labels are what users see).
- Group related nodes inside
subgraph cluster_blocks for visual separation. - Use
rankdir=LRfor wide diagrams, or keep the defaultTBfor top-down flows. - Test with
dot -Tsvgfirst SVG output is resolution-independent and loads fast. - Check for mismatched braces, missing operators, and reserved word conflicts if the output looks wrong.
Save this page as your go-to syntax reference, and when you're ready to build real diagrams, try experimenting with the architecture diagram DOT examples to see these rules applied in context.
Online Dot Graph Editor Tool – Create Graphviz Diagrams Instantly
Graphviz Dot Code Examples for Architecture Diagrams
Visualizing Data Flow with Graphviz Dot Code Examples
Automating Reports with Graphviz Dot Examples
Best Diagram Code Editors for Software Architects in 2025
How to Create a Mermaid Diagram in Markdown Using Mermaid Syntax