How to Export Asset Metadata from AEM
AEM stores rich metadata on every DAM asset. Here are three ways to extract it — from a built-in CSV export to the powerful Query Builder API.
AEM has a built-in CSV metadata export in the Assets UI. Select the items you need, choose "Export Metadata," and download a CSV file containing all metadata fields — no actual files are downloaded, only the metadata. For larger or more targeted exports, the Query Builder API and Assets HTTP API give you programmatic control over which assets and fields to include.
AEM Assets UI — CSV Export
AEM provides a built-in metadata export directly from the Assets user interface. Select the items whose metadata you need, and AEM generates a CSV file with all metadata properties. No actual files are downloaded — only the metadata. This is the fastest path and requires no technical skills.
Query Builder API
The AEM Query Builder is a powerful search API that can find assets by type, path, tag, metadata property, or any combination. It returns JSON that you can convert to CSV. This is the best approach for large DAM repositories where you need to filter or export thousands of assets at once.
/libs/cq/search/content/querydebug.html on your AEM author instance to test queries interactively.# Query all DAM assets under a path
curl -u admin:admin \
"http://localhost:4502/bin/querybuilder.json?\
path=/content/dam/your-folder\
&type=dam:Asset\
&p.limit=-1\
&p.hits=full\
&orderby=path" > aem_assets.json
# Query assets by tag
curl -u admin:admin \
"http://localhost:4502/bin/querybuilder.json?\
path=/content/dam\
&type=dam:Asset\
&tagid=your-namespace:your-tag\
&p.limit=-1\
&p.hits=full" > tagged_assets.jsonimport json, csv
with open("aem_assets.json") as f:
data = json.load(f)
with open("aem_metadata.csv", "w", newline="") as f:
writer = csv.writer(f)
writer.writerow([
"Path", "Title", "Description", "Format",
"Size", "Width", "Height", "Created", "Modified", "Tags"
])
for hit in data.get("hits", []):
props = hit.get("jcr:content", {}).get("metadata", {})
writer.writerow([
hit.get("jcr:path", ""),
props.get("dc:title", ""),
props.get("dc:description", ""),
props.get("dc:format", ""),
props.get("dam:size", ""),
props.get("tiff:ImageWidth", ""),
props.get("tiff:ImageLength", ""),
props.get("jcr:created", ""),
props.get("jcr:lastModified", ""),
", ".join(props.get("cq:tags", [])) if isinstance(props.get("cq:tags"), list) else props.get("cq:tags", ""),
])
print(f"Exported {len(data.get('hits', []))} assets")daterange.property=jcr:content/metadata/jcr:lastModified), specific metadata values, file types (property=jcr:content/metadata/dc:format&property.value=image/jpeg), and more. The Query Builder debugger is invaluable for testing complex queries before scripting them.Assets HTTP API
The AEM Assets HTTP API is a RESTful interface for CRUD operations on DAM assets. It returns well-structured JSON with metadata properties, making it straightforward to convert to any tabular format. It supports pagination for large folder trees.
import requests
import csv
AEM_HOST = "http://localhost:4502"
AUTH = ("admin", "admin")
def list_assets(folder_path="/content/dam/your-folder", limit=20):
"""List assets in a folder with pagination."""
all_assets = []
offset = 0
while True:
url = f"{AEM_HOST}/api/assets{folder_path}.json"
params = {"limit": limit, "offset": offset}
resp = requests.get(url, auth=AUTH, params=params)
data = resp.json()
entities = data.get("entities", [])
if not entities:
break
all_assets.extend(entities)
offset += limit
if len(entities) < limit:
break
return all_assets
assets = list_assets()
with open("aem_metadata.csv", "w", newline="") as f:
writer = csv.writer(f)
writer.writerow([
"Name", "Path", "Title", "Description",
"Format", "Size", "Created", "Modified"
])
for asset in assets:
props = asset.get("properties", {})
metadata = props.get("metadata", {})
writer.writerow([
props.get("name", ""),
asset.get("links", [{}])[0].get("href", "") if asset.get("links") else "",
metadata.get("dc:title", ""),
metadata.get("dc:description", ""),
metadata.get("dc:format", ""),
metadata.get("dam:size", ""),
props.get("created", ""),
props.get("modified", ""),
])
print(f"Exported {len(assets)} assets")What metadata fields can you export?
| Field | Assets CSV Export | Query Builder | Assets HTTP API |
|---|---|---|---|
| Asset title | ✓ | ✓ | ✓ |
| Description | ✓ | ✓ | ✓ |
| File name | ✓ | ✓ | ✓ |
| DAM path | ✓ | ✓ | ✓ |
| File format / MIME type | ✓ | ✓ | ✓ |
| File size | ✓ | ✓ | ✓ |
| Dimensions (width/height) | ✓ | ✓ | ✓ |
| Created date | ✓ | ✓ | ✓ |
| Modified date | ✓ | ✓ | ✓ |
| Created by | ✓ | ✓ | ✓ |
| Tags (cq:tags) | ✓ | ✓ | ✓ |
| Custom metadata schema fields | ✓ | ✓ | ✓ |
| Renditions list | ✕ | Separate query | ✓ |
| Version history | ✕ | JCR query | ✕ |
| Usage references | ✕ | Separate query | ✕ |
| Smart tags (AI) | ✓ | ✓ | ✓ |
- AEM as a Cloud Service vs. On-Premise: The Assets CSV export and Query Builder work on both AEM as a Cloud Service and on-premise installations. The Assets HTTP API behavior may differ slightly between versions. Always test on your specific AEM version.
- Large DAM repositories: The built-in CSV export may time out for folders with tens of thousands of assets. For large-scale exports, use the Query Builder with pagination (
p.offsetandp.limit) or the Assets HTTP API. - Dynamic Media metadata: If you use AEM Dynamic Media, additional metadata like Smart Crop coordinates, video transcoding profiles, and viewer presets are stored in separate nodes and require specific queries.
You have your metadata export.
Now score it.
Upload your CSV or Excel file to MQS and get a structural metadata health score out of 100 with dimension breakdowns and actionable diagnostics.