If you've ever needed to create a flowchart, dependency diagram, or network topology map without dragging boxes around in a GUI, Graphviz and its DOT language are built for exactly that. The DOT language lets you describe graphs in plain text, and a tool called Graphviz turns those descriptions into visual diagrams. Having a solid understanding of the syntax from the start saves you hours of trial and error and that's what this reference is for.
What is the DOT language, and why use it?
DOT is a plain-text graph description language created by AT&T Labs. You write short, readable declarations that describe nodes (the boxes or circles) and edges (the lines connecting them). Graphviz then compiles that text into an image SVG, PNG, PDF, and more.
People use DOT because it works well for:
- Flowcharts and decision trees
- Software architecture and dependency diagrams
- Network and infrastructure topology maps
- State machines and finite automata
- Database relationship diagrams
Unlike visual diagramming tools, DOT files are version-controllable, diffable, and reproducible. You describe what the graph contains, and the layout engine decides where things go.
How is a DOT file structured?
A DOT file has a simple structure. It starts with a graph type declaration, followed by attributes and node/edge definitions inside curly braces.
There are two graph types:
- digraph a directed graph where edges have arrows showing direction
- graph an undirected graph where edges are plain lines (uses
--instead of->)
Here's the skeleton of a directed graph:
digraph {
A -> B
B -> C
}
This creates three nodes (A, B, C) with arrows from A to B and B to C. The layout engine positions them automatically.
How do you define nodes in DOT?
You don't need a separate declaration to create a node mentioning it in an edge creates it. But you can customize nodes by adding attributes after the node name.
A [label="Start", shape=box, style=filled, fillcolor=lightblue]
Common node attributes include:
- label the text displayed inside the node
- shape box, ellipse, circle, diamond, plaintext, hexagon, and many more
- style filled, rounded, dashed, bold, or combinations like "filled,rounded"
- fillcolor background color (requires
style=filled) - color border color
- fontname font family for the label text
- width / height minimum size in inches
You can also set default node attributes that apply to every node in the graph:
node [shape=box, style=filled, fillcolor=lightyellow]
Any node you define after this line will inherit those defaults unless you override them individually.
How do edges work in DOT syntax?
Edges connect nodes using -> for directed graphs or -- for undirected ones. You can chain them and add attributes the same way.
A -> B [label="depends on", color=red, style=dashed]
Common edge attributes include:
- label text displayed along the edge
- color line color
- style solid, dashed, dotted, bold
- arrowhead none, normal, open, diamond, vee, and others
- weight affects how straight and short the edge is drawn (higher = straighter)
- constraint set to false to let an edge not affect ranking
Default edge attributes work the same as node defaults:
edge [color=gray, fontsize=10]
How do you add comments and formatting?
DOT supports C++-style comments:
// single-line comment/ multi-line comment /# single-line comment (shell-style, also works)
Whitespace and line breaks don't matter to the parser, so format your code for readability. Semicolons are optional but can be used to separate statements if you prefer.
What are subgraphs, and when should you use them?
Subgraphs group related nodes together. They're defined with the subgraph keyword and a name that must start with cluster_ if you want Graphviz to draw a bounding box around them.
subgraph cluster_auth {
label="Authentication"
style=dashed
Login -> Validate
Validate -> Token
}
Subgraphs are useful for logically grouping components in architecture diagrams or showing distinct modules. If the name doesn't start with cluster_, the grouping only affects layout, not visual appearance.
What is the difference between DOT graph attributes and node/edge attributes?
Graph-level attributes control the overall appearance and layout. You set them directly in the graph body without attaching them to a specific element.
digraph {
rankdir=LR
bgcolor=white
fontname="Arial"
label="System Architecture"
labelloc=t
nodesep=0.5
ranksep=1.0
}
Key graph attributes:
- rankdir TB (top to bottom, default), LR (left to right), BT, RL
- bgcolor background color of the entire canvas
- label title text for the graph
- nodesep minimum space between nodes (in inches)
- ranksep minimum space between ranks/levels
- dpi resolution for raster output
- overlap controls how overlapping nodes are handled
What is ranking, and how does it control layout?
Ranking determines which nodes appear on the same horizontal or vertical level. DOT uses rank statements for this:
- same forces listed nodes onto the same level
- min puts nodes at the top (or start)
- max puts nodes at the bottom (or end)
- source like min, but also affects connected nodes
- sink like max, but also affects connected nodes
Example:
{rank=same; B; C; D}
This forces nodes B, C, and D to appear at the same vertical level. If you want to go further with rank-based grouping and visual styling, check out the advanced node styling and ranking attributes reference.
What are the most common mistakes beginners make?
- Mixing up
->and--. Use->for digraphs and--for undirected graphs. Using the wrong one causes a syntax error. - Forgetting that node IDs are case-sensitive.
Aandaare two different nodes. - Using special characters in labels without quotes. If your label has spaces, colons, or HTML characters, wrap it in double quotes.
- Not quoting attribute values with special characters.
label=My Labelbreaks. Uselabel="My Label". - Placing attributes in the wrong position. Attributes go inside square brackets after the element they apply to, or in a default statement.
- Expecting exact pixel placement. DOT is a declarative language the layout engine makes positioning decisions. If you need precise control, you may need to switch to a different layout engine like
neatoorfdp.
How do you render a DOT file?
Once you've written your DOT code, you can render it with the dot command-line tool:
dot -Tpng graph.dot -o graph.png
Common output formats (-T flag):
- png raster image
- svg scalable vector image (best for web)
- pdf printable document
- jpg compressed raster image
If you don't want to install Graphviz locally, you can test and preview your code instantly using an online DOT editor with live rendering.
What does a complete beginner example look like?
Here's a simple project dependency graph that puts several concepts together:
digraph project {
rankdir=TB
fontname="Helvetica"
node [shape=box, style="filled,rounded", fillcolor="#e8f4f8"]
edge [color=gray, arrowhead=vee]
subgraph cluster_frontend {
label="Frontend"
style=dashed
HTML -> CSS
HTML -> JS [label="interactivity"]
}
subgraph cluster_backend {
label="Backend"
style=dashed
API -> Database
}
JS -> API [label="requests", style=dashed, color=blue]
}
This creates two grouped sections (Frontend and Backend) with labeled, styled edges showing how they connect.
Quick reference: DOT syntax cheat sheet
- Directed edge:
A -> B - Undirected edge:
A -- B - Node attributes:
A [label="Name", shape=box] - Edge attributes:
A -> B [label="text", color=red] - Graph attributes:
rankdir=LR - Defaults:
node [shape=ellipse]oredge [style=dashed] - Subgraph:
subgraph cluster_name { ... } - Rank:
{rank=same; X; Y; Z} - Render:
dot -Tsvg file.dot -o file.svg
Keep this page bookmarked. When you're ready to move beyond the basics, the advanced styling and ranking guide covers HTML-like labels, complex color schemes, and fine-grained layout control.
Beginner's next-step checklist
- Install Graphviz on your machine or open a live DOT editor to start testing immediately.
- Write a simple 3-node digraph with
A -> B -> Cand render it to SVG. - Add labels and change one node's shape to
diamond. - Group related nodes into a
subgraph cluster_and observe the visual difference. - Change
rankdirfrom TB to LR and see how the layout shifts. - Try the
dot,neato, andfdpengines on the same file to compare layout styles.
Start small, break things, and read the error messages they're usually clear about what syntax you got wrong.
How to Create State Machine Diagrams Using Graphviz Dot Language
Graphviz Dot Online Editor with Live Preview and Export Tools
Graphviz Dot Language vs Mermaid for System Architecture Diagrams
Graphviz Dot Language Advanced Node Styling and Ranking Attributes
E-Commerce Website Database Schema Diagram Example with Tables and Relationships
Online Database Schema Diagram and Code Generator Tool