This specification describes an extension mechanism for the Verifiable Credential Data Model, that can be used to represent a Verifiable Credential through a visual, auditory, or haptic medium. It covers rendering a Verifiable Credential to a physical document, digital image, screen reader, or braille output.
This is an experimental specification and is undergoing regular revisions. It is not fit for production deployment.
Rendering methods can be used when the [=issuer=] has a specific way that they want to express a [=verifiable credential=] to an observer through a visual, auditory, or haptic mechanism. For example, an [=issuer=] of an employee badge credential might want to include rich imagery of their corporate logo and specific placement of employee information in specific areas of the badge. They might also want to provide an audio read out of the important aspects of the badge for individuals that have accessibility needs related to their eyesight.
Some terminology used throughout this document is defined in the Terminology section of the [[[VC-DATA-MODEL-2.1]]] specification.
A conforming render method is any concrete expression of the data model that complies with the normative statements in this specification. Specifically, all relevant normative statements in Sections and of this document MUST be enforced.
A conforming processor is any algorithm realized as software and/or hardware that generates or consumes a [=conforming render method=]. Conforming processors MUST produce errors when non-conforming documents are consumed.
This document also contains examples that contain JSON and JSON-LD content. Some of these examples contain characters that are invalid JSON, such as inline comments (`//`) and the use of ellipsis (`...`) to denote information that adds little value to the example. Implementers are cautioned to remove this content if they desire to use the information as valid JSON or JSON-LD.
The following sections outline the data model that is used by this specification for rendering methods
The `renderMethod` property is a reserved extension point in the [[[VC-DATA-MODEL-2.1]]] specification . An [=issuer=] can utilize this property in a [=verifiable credential=] to express one or more preferred render methods.
When an [=issuer=] desires to specify template-based rendering instructions for a [=verifiable credential=], they MAY add a `renderMethod` property that uses the data model described below.
| Property | Description | ||||||||
|---|---|---|---|---|---|---|---|---|---|
| id | An OPTIONAL [=string=] that follows the [[[URL]]] and, when fetched, dereferences to a render template. | ||||||||
| type | A REQUIRED [=string=] that MUST be the value `TemplateRenderMethod`. | ||||||||
| renderSuite | A REQUIRED [=string=] that identifies the algorithms that are used for generating the concrete rendering. | ||||||||
| name | An OPTIONAL human-readable [=string=] that can be displayed to provide a hint to the type of rendering that will be performed. This property might be used in a graphical interface that enables an individual to select between multiple presentation modes. | ||||||||
| description | An OPTIONAL human-readable [=string=] that provides a more involved description than `name` of when the particular rendering might be useful. | ||||||||
| renderProperty | An OPTIONAL [=list=] of [=string=] values that each conform to the [[[RFC6901]]] syntax that specifies which properties from the [=verifiable credential=] are exposed when using this specific render method. If `renderProperty` is not provided, the entire [=verifiable credential=] is presumed to be shared when the render method is used. | ||||||||
| template |
An OPTIONAL [=URL=] or [=ordered map|map=] that provides or refers to the
template that will be used to perform the rendering. If the value is a [=URL=],
it MAY be a `data:` URL [[RFC2397]] containing the template code. If the value
is a [=ordered map|map=], it MUST conform to the following rules:
|
||||||||
| digestMultibase | An OPTIONAL multibase-encoded Multihash of the render method referenced if `id` is specified. The multibase value MUST be `u` (base64url-nopad) and the multihash value MUST be SHA-2 with 256-bits of output (`0x12`). |
The `card` render suite uses JSON templates to transform a [=verifiable credential=] into a standardized data display format. This format enables wallets to display credentials in a responsive card layout with key data highlighted and configurable additional fields. Wallets that implement this method can render the standardized JSON output in their own card UI designs, allowing credentials to be displayed even when a wallet doesn't natively support a specific credential type.
The template is a JSON object that matches the `card` output structure. String values in the template can be JSON pointer strings (as specified in [[[RFC6901]]]) that reference fields in the [=verifiable credential=]. When processing the template, JSON pointer strings are evaluated against the credential data and replaced with the resolved values. The template MUST conform to the JSON template schema defined below, and the resulting output MUST conform to the `card` output schema. Compound data across multiple fields is not supported; each field references a single JSON pointer.
The template for a `card` render suite MUST be a JSON object that conforms to the following structure. The template structure matches the output structure, but string values can be either literal strings or JSON pointer strings (starting with `/`) that reference fields in the [=verifiable credential=]. The template SHOULD be validated against this schema before processing.
| Property | Type | Description |
|---|---|---|
| name | [=string=] |
A REQUIRED string that is either a literal display name or a JSON pointer
string (e.g., "/credentialSubject/degree/name") that references
the credential data.
|
| description | [=string=] | A REQUIRED string that is either a literal description or a JSON pointer string that references the credential data. |
| icon | [=string=] | An OPTIONAL string that is either a literal URL/data URI or a JSON pointer string that references the credential data. |
| theme | [=ordered map|map=] |
An OPTIONAL color theme object with the following properties:
|
| fields | [=list=] |
A REQUIRED ordered list of custom data fields. Each field is an object with:
|
| validFrom | [=string=] | An OPTIONAL string that is either a literal ISO 8601 date or a JSON pointer string that references the credential data (validity start date). |
| validUntil | [=string=] | An OPTIONAL string that is either a literal ISO 8601 date or a JSON pointer string that references the credential data (validity end date). |
The following JSON Schema implements the template structure rules defined above:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["name", "description", "fields"],
"properties": {
"name": {
"type": "string",
"description": "Display name as a literal string or JSON pointer (e.g., \"/credentialSubject/degree/name\")"
},
"description": {
"type": "string",
"description": "Description as a literal string or JSON pointer"
},
"icon": {
"type": "string",
"description": "Icon URL/data URI as a literal string or JSON pointer"
},
"theme": {
"type": "object",
"properties": {
"primaryColor": {
"type": "string",
"description": "Primary color as a literal string or JSON pointer"
},
"accentColor": {
"type": "string",
"description": "Accent color as a literal string or JSON pointer"
}
},
"additionalProperties": false
},
"fields": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": ["label", "value"],
"properties": {
"label": {
"type": "string",
"description": "Field label (MUST be a literal string, not a JSON pointer)"
},
"value": {
"type": "string",
"pattern": "^/",
"description": "Field value as a JSON pointer string (MUST start with \"/\")"
},
"language": {
"type": "string",
"description": "Optional BCP 47 language tag for the field"
}
},
"additionalProperties": false
}
},
"validFrom": {
"type": "string",
"description": "Validity start date as a literal ISO 8601 date string or JSON pointer"
},
"validUntil": {
"type": "string",
"description": "Validity end date as a literal ISO 8601 date string or JSON pointer"
}
},
"additionalProperties": false
}
The following example shows a valid `card` template with JSON pointer strings:
{
"name": "/credentialSubject/degree/name",
"description": "University Degree Credential",
"icon": "/credentialSubject/icon",
"theme": {
"primaryColor": "#1a5490",
"accentColor": "/credentialSubject/theme/accentColor"
},
"fields": [
{
"label": "Institution",
"value": "/issuer"
},
{
"label": "Degree Type",
"value": "/credentialSubject/degree/type"
},
{
"label": "Issue Date",
"value": "/validFrom"
}
],
"validFrom": "/validFrom",
"validUntil": "/validUntil"
}
The output of a `card` template MUST be a JSON object that conforms to the following structure:
| Property | Type | Description |
|---|---|---|
| name | [=string=] | A REQUIRED display name for the credential card. |
| description | [=string=] | A REQUIRED description text for the credential card. |
| icon | [=string=] | An OPTIONAL URL or data URI for an icon or image to display on the card. |
| theme | [=ordered map|map=] |
An OPTIONAL color theme object with the following properties:
|
| fields | [=list=] |
A REQUIRED ordered list of custom data fields. Each field is an object with:
|
| validFrom | [=string=] | An OPTIONAL ISO 8601 date string indicating when the credential becomes valid. |
| validUntil | [=string=] | An OPTIONAL ISO 8601 date string indicating when the credential ceases to be valid. |
The following example shows a valid `card` output:
{
"name": "Bachelor of Science and Arts",
"description": "University Degree Credential",
"icon": "https://example.edu/icons/degree.svg",
"theme": {
"primaryColor": "#1a5490",
"accentColor": "#4a90e2"
},
"fields": [
{
"label": "Institution",
"value": "Example University"
},
{
"label": "Degree Type",
"value": "BachelorDegree"
},
{
"label": "Graduation Date",
"value": "2010-05-15"
}
],
"validFrom": "2010-01-01T19:23:24Z",
"validUntil": null
}
In the example below, a fully embedded JSON template is used as the rendering template. The template uses JSON pointer strings to reference credential data.
{
...
"renderMethod": {
"type": "TemplateRenderMethod",
"renderSuite": "card",
// the JSON template is embedded in the VC
"template": "data:application/json;base64,eyJuYW1lIjogIi9jcmVkZW50aWFsU3ViamVjdC9kZWdyZWUvbmFtZSIsICJkZXNjcmlwdGlvbiI6ICJVbml2ZXJzaXR5IERlZ3JlZSBDcmVkZW50aWFsIiwgImZpZWxkcyI6IFt7ImxhYmVsIjogIkluc3RpdHV0aW9uIiwgInZhbHVlIjogIi9pc3N1ZXIifV19"
}
}
The next example links to the JSON template on the Web and secures it against modification by using the `digestMultibase` property.
{
...
"renderMethod": {
"type": "TemplateRenderMethod",
"renderSuite": "card",
"template": {
// this JSON template is fetched from the Web
"id": "https://degree.example/credential-templates/bachelors.json",
"mediaType": "application/json",
"digestMultibase": "zQmerWC85Wg6wFl9znFCwYxApG270iEu5h6JqWAPdhyxz2dR"
}
}
The next example links to the rendering template on the Web and secures it using the `digestMultibase` property:
{
...
"renderMethod": {
// this render method is fetched from the Web
"id": "https://degrees.example/bachelors-card.jsonld",
"mediaType": "application/ld+json",
"type": "TemplateRenderMethod",
"renderSuite": "card",
"digestMultibase": "zQmG270iEu5h6JqWAPdhyxz2dRerWC85Wg6wFl9znFCwYxAp"
}
The `html` render suite allows template authors to provide an HTML template to render a [=verifiable credential=]. The HTML can be referenced remotely or via a `data:` URL as the value of either `template` or `template.id` (when the value of `template` is an object). JavaScript within the HTML fragment is responsible for rendering the filtered [=verifiable credential=] data provided via an HTML data block (i.e. `<script type="application/vc"></script>`) hosted in a sandboxed iframe alongside the HTML template.
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://www.w3.org/ns/credentials/examples/v2"
],
"type": [
"VerifiableCredential",
"NameCredential"
],
"issuer": {
"id": "did:example:1234",
"name": "The Issuer"
},
"credentialSubject": {
"name": "Example Name",
"notRendered": "should not appear"
},
"renderMethod": {
"type": "TemplateRenderMethod",
"renderSuite": "html",
"renderProperty": [
"/issuer/name",
"/credentialSubject/name"
],
"template": {
"id": "https://test.example/credential-templates/NameCredential.html",
"mediaType": "text/html",
"digestMultibase": "zQmerWC85Wg6wFl9znFCwYxApG270iEu5h6JqWAPdhyxz2dR"
},
"outputPreference": {
"accessMode": [
"visual"
],
"mediaType": "application/html",
"style": {
"width": "800px",
"height": "800px"
}
}
}
}
Implementations MUST provide an environment that allows for JavaScript to safely render the HTML template using the filtered [=verifiable credential=] data. Additionally, a [=host page=] SHOULD protect the privacy of any request made (for example, dereferencing `template.id`) by using Oblivious HTTP [[?RFC9458]] or other means of disassociating the requesting client from the requested origin by using a protecting relay.
The following terminology is used to describe this environment:
At minimum, the environment MUST prevent navigation, loading of external content, and access to the [=host page=] in order to prevent tracking and other privacy harms.
Browser based implementations, for example, can provide such an environment using a combination of Content Security Policy [[CSP3]] restrictions on a [=host page=], sandboxing of an `iframe` hosting the HTML template, and wrapper code that wraps the HTML template to add additional CSP restrictions and provides ready and error event communication with the [=host page=].
graph TD
subgraph Wallet's VC Rendering HTML
direction LR
A(VC) -- selectively disclosed --> B{VC subset datablock}
subgraph "iframe[srcdoc] wrapper code"
B{VC subset datablock}
C[HTML/CSS/JS template from renderMethod]
end
C[HTML/CSS/JS template from renderMethod] --> D[renderMethodReady]
end
The [=host page=] (typically a Wallet or [=verifiable credential=] renderer) MUST prevent the HTML template from navigating the top-level browsing context, accessing external content, accessing the [=host page=], and loading any remote content.
If a [=host page=] is used, the following rules apply:
The HTML [=template code=] referenced by the `template` property in the `renderMethod` MUST be an HTML fragment that contains the HTML, CSS, and JavaScript necessary to render the [=verifiable credential=]. The [=template code=] MUST NOT include any `<html>`, `<head>`, or `<body>` tags, as these will be provided by the [=wrapper code=].
The template HTML fragment MUST be wrapped in [=wrapper code=] that provides the data block containing the partial [=verifiable credential=] and adds an additional CSP policies to prevent navigation and external content loading. Specifically, the [=wrapper code=] MUST add the following CSP restrictions of `default-src data: 'unsafe-inline'` to prevent any network requests from being made by the [=template code=].
To complete the setup, the [=host page=] MUST inject the [=wrapper code=] (once populated with the [=verifiable credential=] and the [=template code=]) into the iframe's `srcdoc` attribute which will run any JavaScript contained in the [=wrapper code=] and [=template code=].
The iframe created in the [=wrapper code=] MUST provide a communication channel to allow the template to notify the [=host page=] when rendering is complete or if there was an error during rendering. This can be accomplished using the `postMessage` API with a `MessageChannel` setup by the [=wrapper code=].
The JavaScript shown below would be added to the above [=host page=] to add an `onload` event to the iframe which sets up the `MessageChannel`. The [=host page=] also creates a `Promise` that resolves when a `ready` message is received from the [=wrapper code=] or rejects when an `error` message is received. The [=wrapper code=] also provides a `window.renderMethodReady` method for use by the template to notify the [=host page=] that rendering is complete or send back an error message.
With this setup, the template JavaScript can call `window.renderMethodReady()` to notify the [=host page=] that rendering is complete or call `window.renderMethodReady(new Error("error message"))` to notify the [=host page=] of an error.
Rendering environment preferences MAY be provided within the Render Method. The purpose of this object is to provide suggested use, display, and intended access mode when rendering the provided template. An implementation SHOULD follow these preferences when provided.
| Property | Description |
|---|---|
| outputPreference | An OPTIONAL [=map=] that expresses the preferred rendering environment for the provided template. |
The `outputPreference` object MAY contain any of the following properties:
| Property | Description |
|---|---|
| accessMode | An OPTIONAL [=list=] of one or more [=string=] values of `auditory`, `tactile`, `textual`, or `visual` as defined in https://w3c.github.io/cg-reports/a11y-discov-vocab/CG-FINAL-vocabulary-20260128/#accessMode-vocabulary |
| mediaType | An OPTIONAL [=string=] stating a valid media type listed in the IANA Media Types preferred for rendering. This value MAY be used when suggesting addtional processing prior to rendering. Examples include converting an SVG template into a static image or an HTML document into a PDF. |
| style | An OPTIONAL [=map=] which defines style properties to potentially be used by the rendering environment. |
The `style` object MAY contain any of the following properties:
| Property | Description |
|---|---|
| width | An OPTIONAL [=string=] containing a CSS compatible width preference to be set on the `iframe`. |
| height | An OPTIONAL [=string=] containing a CSS compatible height preference to be set on the `iframe`. |
The `nfc` render suite transmits a binary payload representing the [=verifiable credential=] over a wireless NFC connection.
In the example below, a fully embedded NFC payload is used as the rendering template, which only discloses the barcode identifier associated with the credential.
{
...
"renderMethod": {
"type": "TemplateRenderMethod",
"renderSuite": "nfc",
"name": "Tap to send",
// the NFC payload is embedded
"template": "data:application/octet-stream;base64,2QZkpQGDG...G8XJWnROcY4Biw",
// only the barcode is transmitted over NFC
"renderProperty": ["/credentialSubject/barcode"]
}
...
}
The following sections outline the algorithms that is used by this specification for rendering methods.
When processing a `card` template, the following steps MUST be performed:
Note that compound data across multiple fields is not supported. Each field in the template references a single JSON pointer that resolves to a single value from the credential.
The following sections outline the algorithms that are used by the `html` render suite to safely render the HTML template. Alternative algorithms MAY be used as long as the security and privacy outcomes as well as the output is the same.
The [=host page=] MUST create an `iframe` element to host the HTML template. The [=host page=] MUST set the `sandbox` attribute on the `iframe` to `allow-scripts` to prevent navigation and top-level access.
The [=host page=] MUST filter the [=verifiable credential=] `vc` to only include the properties specified in `renderMethod.renderProperty`, if it is present. If `renderMethod.renderProperty` is not present, the entire [=verifiable credential=] is used.
This filtering MUST be done by applying the `selectJsonLd` algorithm defined in Section 3.4.13 selectJsonLd of the Data Integrity ECDSA Cryptosuites v1.0 specification [[VC-DI-ECDSA]] to the JSON Pointer [[RFC6901]] values present in `renderMethod.renderProperty`.
The [=host page=] MUST create the [=wrapper code=] by embedding the filtered [=verifiable credential=] and the HTML template into the [=wrapper code=] template defined above.
The [=host page=] MUST set the `srcdoc` attribute of the `iframe` to the resulting [=wrapper code=].
The [=host page=] MUST setup a communication channel with the [=wrapper code=] to receive `ready` and `error` messages as described above.
The [=host page=] SHOULD use the `renderPromise` to determine when rendering is complete or if there was an error during rendering.
The [=wrapper code=] MUST setup to receive communication from the [=host page=] via the `MessageChannel` and provide the `window.renderMethodReady` method for use by the [=template code=].
This section summarizes the threat model for this specification, covering the security and privacy considerations relevant to the publication, retrieval, and processing of render methods. The full analysis, including responses and the data flow diagram, is provided in the Verifiable Credentials Render Method Threat Model.
Readers are urged to familiarize themselves with the general threat model provided in the Threat Model section of the [[[VC-DATA-MODEL-2.1]]] specification before reading this section. Implementers are expected to apply the general analysis provided in that specification to each specific feature provided by this specification.
W3C is migrating to a holistic threat modelling approach and is in the process of deprecating the Security Considerations sections in new specifications. Please refer to Appendix [[[#threat-model]]] for documentation related to security considerations.
W3C is migrating to a holistic threat modelling approach and is in the process of deprecating the Privacy Considerations sections in new specifications. Please refer to Appendix [[[#threat-model]]] for documentation related to privacy considerations.
Several existing approaches and technologies were considered for conveying an issuer-preferred, human-perceivable presentation of a [=verifiable credential=]. This section summarizes those alternatives and why the render method approach described in this specification was chosen.
Defining no mechanism and leaving presentation to the [=holder=] or [=verifier=] software requires no extra data, but gives the [=issuer=] no way to convey intended presentation, so credentials render inconsistently and claims or branding can be misrepresented, as described in Uncontrolled Credential Presentation. Credential formats such as ISO/IEC 18013-5 mobile driving licence (mDL) and the JSON Web Tokens (RFC 7519) take this approach, defining the claims a credential carries but leaving their presentation to the consuming software. Microsoft's Information Card (CardSpace), now discontinued, took a limited variant of this, letting an [=issuer=] supply only a card name and logo that the identity selector rendered in a uniform card chrome. This specification adds an issuer-asserted alternative rather than prohibiting client-determined rendering.
Standardizing presentation per credential type via a registry gives consistent renderings for well-known types but requires prior knowledge of each type, does not scale to custom credentials, and cannot express issuer-specific branding. Platform wallets such as Apple Wallet (PassKit), Google Wallet, and Samsung Wallet take this approach, rendering a fixed set of predefined pass or object types in fixed, platform-controlled layouts where an [=issuer=] can fill in field values and assets but cannot express layout or branding outside the platform's catalog. The render method strategy defined by this specification instead travels with or is referenced from the credential, so even an unfamiliar type can be rendered as intended by its issuer.
Such a centralized, controlled, registry-focused solution also works against the distributed, decentralized, and permissionless patterns otherwise specified to be part of the ecosystem of [[[DID|Decentralized Identifiers (DIDs)]]] and [[[VC-DATA-MODEL|Verifiable Credentials (VCs)]]].
Distributing a fully-rendered PDF, static SVG, or HTML document is self-contained and widely supported, but such snapshots do not adapt to selective disclosure, cannot be re-rendered from the verified data, and are not bound to what was secured. This specification reuses these formats as templates combined with claim values at render time rather than as finished documents.
Rather than defining a new integrity mechanism, this specification relies on existing securing mechanisms such as [[[VC-DATA-INTEGRITY]]] and the [[[VC-DATA-INTEGRITY#resource-integrity|digestMultibase]]] property to bind a referenced template to the credential. Readers can learn about these general protection mechanisms by reading about the Tampering with Unprotected External Resources threat in the Verifiable Credential Threat Model.
SD-JWT VC defines a `rendering` property to choose between a `simple` method that supports a fixed set of styling attributes, and an `svg_templates` method that forbids any code execution and substitutes claim values into text placeholders in an SVG. The group explored this approach and found it too limited for real-world use cases: because placeholders appear only in text nodes and no code can run, data-driven presentation tools such as conditional fields, variable-length lists, value formatting, and responsive layout cannot be expressed. These features are requirements in sectors such as healthcare, retail, and banking/finance. In contrast, this specification is not tied to a single credential serialization, and instead defines render suites that span a code-free declarative `card` suite, a data-driven `html` suite executed in a confined, "sandboxed" environment, and a static `nfc` suite.