This guide covers advanced entity features including overlays, links, notes, weights, and display fields.
**Client availability:** Maltego Graph Browser partially supports overlays: it renders icon URL overlays in the southwest position only. Color and text overlays, other overlay positions, and entity weight require Maltego Graph Desktop. Links, notes, display information, and custom entity icons work in both clients.Overlays
Overlays add visual indicators around entity icons. There are three types:
- Color: Colored indicators
- Text: Text labels
- Image: Small images
Overlay Positions
| Position | Location |
|---|---|
OverlayPositions.CENTER | Center of entity |
OverlayPositions.NORTH | Top |
OverlayPositions.NORTHWEST | Top-left |
OverlayPositions.SOUTH | Bottom |
OverlayPositions.SOUTHWEST | Bottom-left |
OverlayPositions.WEST | Left |
Color Overlays
from maltego.model.entity import OverlayTypes, OverlayPositions
@register_transform(...)
async def add_color_overlay(entity: Phrase) -> Phrase:
# Set property with color value
entity.set_property("status_color", "red", display_name="Status")
# Add overlay referencing the property
entity.add_overlay(
OverlayTypes.COLOR,
OverlayPositions.NORTH,
"status_color" # Property name containing color
)
return entityText Overlays
@register_transform(...)
async def add_text_overlay(entity: Phrase) -> Phrase:
# Set property with text
entity.set_property("count", "42", display_name="Count")
# Add text overlay
entity.add_overlay(
OverlayTypes.TEXT,
OverlayPositions.SOUTH,
"count"
)
return entityImage Overlays
@register_transform(...)
async def add_image_overlay(entity: Phrase) -> Phrase:
# Set property with image URL
entity.set_property("flag", "https://example.com/flag.png", display_name="Flag")
# Add image overlay
entity.add_overlay(
OverlayTypes.IMAGE,
OverlayPositions.NORTHWEST,
"flag"
)
return entityLinks
Control how links between entities appear.
Link Properties on Entity Creation
from maltego.model.types import LinkThickness, LinkStyle, LinkColor
entity = Phrase(
"Connected",
reverse_link=True, # Arrow points to parent
link_thickness=LinkThickness.THICKNESS_4,
link_style=LinkStyle.DOTTED,
link_color=LinkColor.RED,
link_label="related to"
)Link Properties When Adding to Graph
from maltego.entities import Phrase
from maltego.model.types import LinkThickness, LinkStyle, LinkColor
from maltego.server import MaltegoContext, register_transform
@register_transform(...)
async def custom_links(entity: Phrase, context: MaltegoContext) -> None:
graph = context.graph
child = graph.add_entity(Phrase("Child"))
graph.add_link(
entity, # Source
child, # Target
is_reversed=True,
thickness=LinkThickness.THICKNESS_3,
style=LinkStyle.DASHDOT,
color=LinkColor.BLUE,
label="parent of"
)
return None # Return None when using graph directlyLink Styles
| Style | Appearance |
|---|---|
LinkStyle.NORMAL | Solid line |
LinkStyle.DASHED | Dashed line |
LinkStyle.DOTTED | Dotted line |
LinkStyle.DASHDOT | Dash-dot pattern |
Link Thickness
| Thickness | Size |
|---|---|
LinkThickness.THICKNESS_DEFAULT | Default |
LinkThickness.THICKNESS_1 | Thinnest |
LinkThickness.THICKNESS_2 | Thin |
LinkThickness.THICKNESS_3 | Medium |
LinkThickness.THICKNESS_4 | Thickest |
Link Colors
| Color | Value |
|---|---|
LinkColor.NONE | No color (default) |
LinkColor.BLUE | Blue |
LinkColor.GREEN | Green |
LinkColor.YELLOW | Yellow |
LinkColor.PURPLE | Purple |
LinkColor.RED | Red |
Custom Link Properties
from maltego.model.link import MaltegoLinkProperty
graph.add_link(
source,
target,
properties={
"confidence": MaltegoLinkProperty(
name="confidence",
value="0.95",
display_name="Confidence Score"
)
}
)Entity Notes
Add text notes to entities:
@register_transform(...)
async def add_note(entity: Phrase, context: MaltegoContext) -> Phrase:
# Add a note
entity.note = "This entity was found in the database"
# Or append to existing note
if entity.note:
entity.note += "\nAdditional information"
return entityEntity Weight
Control entity importance/ranking:
@register_transform(...)
async def weighted_results(entity: Phrase) -> List[Phrase]:
return [
Phrase("Most important", weight=1000),
Phrase("Medium importance", weight=100),
Phrase("Less important", weight=10),
]Higher weights make entities appear more prominent.
Dynamic Icons
Set entity icons dynamically via URL:
@register_transform(...)
async def custom_icon(entity: Phrase) -> Phrase:
result = Phrase("Custom Icon")
result.icon_url = "https://example.com/icon.png"
return resultDisplay Fields
Add rich display information to entities:
**Security note — display-field HTML is sanitized by default.** All display-field content (both markdown-converted HTML and raw HTML passed via ``add_display_field_html`` / ``add_display_label``) is run through an allow-list sanitizer before being stored in the entity response.
**What is preserved:** headings (``h1``-``h6``), paragraphs, lists (``ul``/``ol``/``li``), links (``a href``), images (``img src``), emphasis (``strong``, ``em``, ``b``, ``i``), tables (``table``/``tr``/``th``/``td``), code blocks (``code``, ``pre``), and common block-level elements (``div``, ``span``, ``blockquote``).
**What is stripped:** ``<script>`` tags, all inline event handlers (``onclick``, ``onerror``, and any other ``on*`` attributes), ``javascript:`` and ``data:`` URLs, and HTML comments.
Callers must not rely on raw HTML or script injection surviving in display fields — such content will be silently removed by the sanitizer.Markdown Display Field
@register_transform(...)
async def markdown_display(entity: Phrase, context: MaltegoContext) -> Phrase:
entity.add_display_field_markdown(
name="Description",
value="## Summary\n\n**Bold text** and *italic*\n\n- Item 1\n- Item 2"
)
return entityHTML Display Field
@register_transform(...)
async def html_display(entity: Phrase, context: MaltegoContext) -> Phrase:
entity.add_display_field_html(
name="Details",
value="<h2>Details</h2><p>HTML <strong>content</strong></p>"
)
return entityHTML Helpers
The pagination example (transforms/pagination_example.py) includes reusable HTML helpers:
from html import escape
from typing import Any, Dict, List, Optional, Union
def html_table(data: Dict[str, Any], title: Optional[str] = None) -> str:
"""Build an HTML table from a dictionary."""
rows = []
for key, value in data.items():
if value is None or value == "":
continue
safe_key = escape(str(key))
safe_value = escape(str(value))
rows.append(f"<tr><td><strong>{safe_key}</strong></td><td>{safe_value}</td></tr>")
table_html = f'<table style="border-collapse: collapse; width: 100%;">{"".join(rows)}</table>'
if title:
return f"<h3>{escape(title)}</h3>{table_html}"
return table_html
def html_link(url: str, text: Optional[str] = None) -> str:
"""Create a clickable HTML link."""
safe_url = escape(url)
safe_text = escape(text or url)
return f'<a href="{safe_url}" target="_blank">{safe_text}</a>'
def html_list(items: List[Union[str, Dict[str, Any]]], ordered: bool = False) -> str:
"""Build an HTML list from items."""
tag = "ol" if ordered else "ul"
list_items = []
for item in items:
if isinstance(item, dict):
list_items.append(f"<li>{html_table(item)}</li>")
else:
list_items.append(f"<li>{escape(str(item))}</li>")
return f"<{tag}>{''.join(list_items)}</{tag}>"Example: Artwork Details
# Build rich display field for artwork
details = {
"Title": title,
"Artist": artist,
"Date": item.get("date_display"),
"Medium": item.get("medium_display"),
}
html_content = html_table(details)
html_content += f"<p>{html_link(full_url, 'View Image')}</p>"
entity.add_display_field_html("Artwork Details", html_content)See transforms/pagination_example.py for the complete implementation using the Art Institute of Chicago API.
Complete Example
Run maltego-transforms start my_project to create a new project from the template. See transforms/entity_features_example.py for runnable examples of all entity features covered in this guide.