?um/p1-90`The document at https://tc54.org/ecma427/ is the most accurate and up-to-date Package-URL specification.
This document is available as a single page and as multiple pages.
This specification is developed on GitHub with the help of the Package-URL community. There are a number of ways to contribute to the development of this specification:
Refer to the
Software ecosystems have evolved into highly interconnected networks of components, packages, and dependencies. Managing this complexity demands a robust, uniform mechanism to identify and track software packages across diverse ecosystems and tools. Package-URL (PURL) was developed to address this challenge by providing a simple, consistent, and flexible approach to identifying software packages with precision and clarity.
PURL introduces a standardized URL-based syntax that uniquely identifies software packages, independent of their ecosystem or distribution channel. Unlike traditional identification methods, PURL embeds critical metadata directly into its structure, enabling efficient, accurate package identification at scale. This standardization ensures interoperability between tools and ecosystems, fostering greater collaboration and reducing ambiguity in software supply chain management.
Challenges addressed by PURL:
As software supply chain security becomes a global priority, formalizing PURL as an international standard ensures its adoption and consistent implementation. Standardization under Ecma International Technical Committee 54 (TC54) positions PURL as a foundational building block for secure, transparent, and efficient software ecosystems worldwide.
By enabling a universally recognized and implementable specification, PURL aligns with global efforts to improve the security, reliability, and accountability of software supply chains. Its adoption ensures that organizations and developers can rely on a common language to manage software packages across the diverse and rapidly evolving software landscape.
This Standard defines the Package-URL (PURL) syntax for identifying software packages independently of their ecosystem or distribution channel. PURL is used to identify software packages across software supply chains supporting many use cases, identifying software packages in Software Bills of Materials, vulnerability databases, vulnerability advisories, vulnerability disclosures and exploitability reports, and managing software package dependencies.
A PURL is a valid URL and
A conforming implementation of Package-URL (PURL) shall fully implement and support all elements defined within this Standard, including the syntax, components, and semantic requirements for constructing and interpreting valid PURLs.
A conforming implementation of PURL shall adhere to the syntax defined in this Standard, ensuring that all PURLs are parsed, constructed, and validated according to the prescribed rules. The implementation shall provide full support for ecosystem-agnostic behaviour, enabling PURLs to function consistently and reliably across diverse environments.
All required components of a PURL, such as the scheme, type, and name, shall be present and validated according to the rules defined in this Standard. Additionally, optional components, including qualifiers and subpaths, shall be handled appropriately if provided, in full compliance with their specified behaviours.
Implementations shall ensure that equivalent PURLs are consistently resolved to the same canonical representation. This includes strict adherence to normalization and equivalence rules. Furthermore, implementations shall process
Invalid PURLs that fail to conform to the specification shall be identified and rejected by any conforming implementation. This guarantees the integrity and reliability of PURLs in all supported contexts.
A conforming implementation of PURL may extend its functionality by providing ecosystem-specific validation, processing, or metadata handling, as long as these extensions do not violate the core specification. Additionally, implementations may offer auxiliary tools or features, such as utilities for constructing or validating PURLs, provided they align with the standard's requirements.
A conforming implementation shall not redefine or alter the core syntax, components, or semantics defined by this Standard. Any prohibited extensions explicitly identified in the specification shall not be implemented. Furthermore, behaviours that compromise the interoperability of PURLs across tools, platforms, or ecosystems are strictly disallowed.
The verbal forms in this Standard follow ISO/IEC Directives, Part 2: shall and shall not indicate requirements; should and should not indicate recommendations; may and need not indicate permission; and can and cannot indicate possibility or capability. The verbal form must is used only for external constraints and does not express a requirement of this Standard.
The following documents are referred to in the text in such a way that some or all of their content constitutes requirements of this document. For dated references, only the edition cited applies. For undated references, the latest edition of the referenced document (including any amendments) applies.
ECMA-262, ECMAScript® language specification
https://ecma-international.org/publications-and-standards/standards/ecma-262/
IETF RFC 3629,
https://datatracker.ietf.org/doc/html/rfc3629
IETF RFC 3986, Uniform Resource Identifier (
https://datatracker.ietf.org/doc/html/rfc3986
IETF RFC 5234, Augmented BNF for Syntax Specifications:
https://datatracker.ietf.org/doc/html/rfc5234
The
https://www.unicode.org/versions/latest/
This Clause contains a non-normative overview of the Package-URL specification.
The Package-URL (PURL) specification defines a lightweight, universal syntax for identifying software packages. By leveraging a URL-based format, PURL provides a consistent and interoperable mechanism for referencing software packages across a wide range of ecosystems and tools. Its design addresses the challenges of ambiguity, inconsistency, and fragmentation in software package identification, enabling better interoperability and traceability in modern software supply chains.
This Standard focuses on the core aspects of PURL, including its syntax, required components, optional attributes, and conformance requirements. It does not cover ecosystem-specific types or extensions such as PURL Version Ranges (
The primary audience for this Standard includes developers, tool implementers, and organizations involved in software composition analysis, dependency management, and supply chain security. PURL is foundational to a variety of use cases, from software bill of materials (SBOM) generation and licence compliance to vulnerability tracking and software artefact exchange.
While this document serves as the authoritative reference for implementing PURL, it is complemented by various ecosystem-specific guidance documents, examples, and related standards. These resources provide additional context and practical insights for leveraging PURL effectively.
This overview is non-normative and serves to provide context for the specification’s intent, purpose, and audience. For detailed requirements and conformance criteria, refer to the normative clauses of this Standard.
PURL stands for Package-URL.
A PURL is a URL composed of seven components:
scheme:type/namespace/name@version?qualifiers#subpath
Components are separated by a specific character for unambiguous parsing.
| Component | Requirement | Description |
|---|---|---|
| scheme | Required | The URL scheme with the constant value of "pkg". One of the primary reasons for this single scheme is to facilitate the future official registration of the "pkg" scheme for Package-URLs. |
| type | Required | The package "type" or package "protocol" such as maven, npm, nuget, gem, pypi, etc. |
| namespace | Optional | A name prefix such as a Maven groupid, a Docker image owner, a GitHub user or organization. Namespace is type-specific. |
| name | Required | The name of the package. |
| version | Optional | The version of the package. |
| qualifiers | Optional | Qualifier data for a package such as OS, architecture, repository, etc. Qualifiers are type-specific. |
| subpath | Optional | Subpath within a package, relative to the package root. |
Components are designed such that they form a hierarchy from the most significant on the left to the least significant components on the right.
A PURL shall not contain a URL Authority, i.e. there is no support for username, password, host and port components. A namespace segment may sometimes look like a host, but its interpretation is specific to a type.
pkg:deb/debian/curl@7.50.3-1?arch=i386&distro=jessie
pkg:maven/org.apache.xmlgraphics/batik-anim@1.9.1?packaging=sources
pkg:npm/foobar@12.3.1
A PURL is a valid URL and
The PURL components are mapped to these URL components:
scheme: this is a URL scheme with a constant value: pkg.type, namespace, name and version components: these are collectively mapped to a URL path.qualifiers: this maps to a URL query.subpath: this is a URL fragment.In a PURL, there is no support for a URL Authority (e.g. no username, password, host and port components).
Special URL schemes as defined in file://, https://, http:// and ftp:// are not valid PURL types. They are valid URL or
Version control system (VCS) URLs such as git://, svn://, hg:// or as defined in Python pip or SPDX download locations are not valid PURL types. They are valid URL or
A PURL should be a locator based on three paths to specify or derive a URL:
type.qualifier for a PURL type.A valid PURL is composed of these permitted ASCII characters:
A to Z, a to z, 0 to 9;.-_~ (period '.', dash '-', underscore '_', and tilde '~');% (percent sign '%');:/@?=&# (colon ':', slash '/', at sign '@', question mark '?', equal sign '=', ampersand '&', and hash sign '#').This is how each of the separator characters is used:
scheme and type.type, namespace and name.subpath segments.name and version.qualifiers.key and a value of a qualifier.qualifiers (each being a key=value pair).subpath.In the
When percent-encoding is required by a component definition, the component string shall first be encoded as
In the component string, each "data octet" shall be replaced by the percent-encoded "character triplet" applying the percent-encoding mechanism defined in
The following characters shall not be
Where the space ' ' is permitted, it shall be
With the exception of the percent-encoding mechanism, the rules regarding percent-encoding are defined by this Standard alone.
References to "lowercase" in this Standard refer to the culture-invariant full case mapping defined in Section 3.13.2 of the
When applied to the ASCII character set, this operation converts uppercase Latin letters (A to Z) to their corresponding lowercase forms (a to z). All other ASCII characters remain unchanged.
A PURL string is an ASCII URL string composed of seven components. Except as expressly stated otherwise in this Clause, each component:
The "
scheme is a constant with the value "pkg".scheme shall be followed by an unencoded colon ':'.scheme and colon ':' are followed by one or more slash '/' characters, such as 'pkg://', and should ignore and remove all such '/' characters.type shall be composed only of ASCII letters and numbers, period '.', and dash '-'.type shall start with an ASCII letter.type shall not be type is case-insensitive. The form is namespace is optional, unless required by the package's type definition.namespace may contain one or more segments, separated by a single unencoded slash '/' character.namespace.namespace segment shall be a type definition further restricts the allowed characters.namespace. Use instead a repository_url qualifier. Note however, that for some types, the namespace may look like a host.name is prefixed by a single slash '/' separator when the namespace is not empty.name.name shall be a name may contain any type definition further restricts the allowed characters.version is prefixed by a '@' separator when not empty.version.version shall be a version may contain any type definition further restricts the allowed characters.version is a plain and opaque string.qualifiers component shall be prefixed by an unencoded question mark '?' separator when not empty. This '?' separator is not part of the qualifiers component.qualifiers component is composed of one or more key=value pairs. Multiple key=value pairs shall be separated by an unencoded ampersand '&'. This '&' separator is not part of an individual qualifier.key and value shall be separated by the unencoded equal sign '=' character. This '=' separator is not part of the key or value.value shall not be an empty string: a key=value pair with an empty value is the same as if no key=value pair exists for this key.key=value pair:
key shall be composed only of key shall start with an ASCII letter.key shall not be key shall be unique among all the keys of the qualifiers component.value may contain any subpath string is prefixed by a '#' separator when not empty.subpath.subpath may contain one or more segments, each separated by a single unencoded slash '/' character.subpath segment shall be a type definition further restricts the allowed characters.subpath shall be interpreted as relative to the root of the package.This Standard includes the Package-URL Type Definition Schema, but it does not include the set of current "registered" PURL type (JSON format) definition files because there are ongoing additions and changes to these files. The set of current "registered" PURL type definition files are located at: https://www.packageurl.org/purl-types/. Registration refers to the Package-URL community process for adding a new PURL type.
There are two rules related to the set of registered PURL type definitions for conforming PURL implementations to validate the PURL type component of a PURL:
type is registered, then the PURL is invalid if it does not conform to all of the rules from the corresponding PURL type definition.type is not registered, then the type component is valid if it conforms to the rules stated in the type is not registered.The PURL Type Definition JSON Schema is the reference data model that is used to define PURL types in a structured way. Each PURL type is specified in a JSON document that matches this schema. These JSON documents are then used to generate PURL type documentation and to support PURL libraries and tools so that they can more easily parse, build, and validate PURLs by type in a consistent and standardized manner across programming languages and technology stacks.
The PURL Type Definition Schema is formally specified by a Draft 07 JSON Schema. Each published version of the Standard is accompanied by a versioned meta-schema at a stable
https://packageurl.org/schemas/purl-type-definition.schema-<major>.<minor>.json
Location: /
Type: Object
Schema to specify a Package-URL (PURL) type as a structured definition.
| Property | Type | Requirement | Description |
|---|---|---|---|
| type | String | Required | The type string for this Package-URL type. |
| type_name | String | Required | The name for this PURL type. |
| description | String | Required | The description of this PURL type. |
| repository | Object | Required | The package repository usage for this PURL type. |
| namespace_definition | Array | Required | Definition of the namespace component for this PURL type. The PURL namespace component shall be required, optional or prohibited for a specific PURL type definition. |
| name_definition | Array | Required | Definition of the name component for this PURL type. The PURL name component is required for all PURL type definitions. |
| version_definition | Array | Optional | Definition of the version component for this PURL type. The PURL version component is optional for a specific PURL type definition. |
| qualifiers_definition | Array | Optional | Definition of the qualifiers specific to this PURL type. The PURL qualifiers component is optional for a specific PURL type, but a qualifiers key or keys may be required for a specific PURL type. |
| subpath_definition | Array | Optional | The definition for the subpath for this PURL type. The PURL subpath component is optional for a specific PURL type definition. |
| examples | Array | Required | Example of valid PURLs for this package type. |
| note | String | Optional | Note about this PURL type. |
| reference_urls | Array | Optional | Optional list of informational reference URLs about this PURL type. |
Location: /type
Property: type (Required)
Type: String
Pattern Constraint: ^[a-z][a-z0-9-\.]+$
The type string for this Package-URL type.
Location: /type_name
Property: type_name (Required)
Type: String
The name for this PURL type.
Location: /description
Property: description (Required)
Type: String
The description of this PURL type.
Location: /repository
Property: repository (Required)
Type: Object
The package repository usage for this PURL type.
| Property | Type | Requirement | Description |
|---|---|---|---|
| use_repository | Boolean | Required | true if this PURL type uses a public package repository. |
| default_repository_url | String | Optional | The default public repository URL for this PURL type. |
| note | String | Optional | Extra note text. |
Location: /repository/use_repository
Property: use_repository (Required)
Type: Boolean
true if this PURL type uses a public package repository.
Location: /repository/default_repository_url
Property: default_repository_url (Optional)
Type: String
Format:
The default public repository URL for this PURL type.
Location: /repository/note
Property: note (Optional)
Type: String
Extra note text.
Location: /namespace_definition
Property: namespace_definition (Required)
Type: Object
Definition of the namespace component for this PURL type. The PURL namespace component shall be required, optional or prohibited for a specific PURL type definition.
| Property | Type | Requirement | Description |
|---|---|---|---|
| requirement | Array | Required | States that the PURL namespace component is optional, required or prohibited for a PURL type. |
| registered_values | Array | Optional | Optional set of registered namespace values for this PURL type. If the namespace value for a PURL of this type is not one of these registered values, a tool should report a warning. The registered namespace values should be sorted lexicographically. |
| permitted_characters | String | Optional | A regular expression ( |
| case_sensitive | Boolean | Optional | true if this PURL component is case-sensitive. If false, the form shall be |
| normalization_rules | Array | Optional | List of rules to normalize this component for this PURL type. These are plain text, unstructured rules as some require programming and cannot be enforced only with a schema. Tools are expected to apply these rules programmatically. |
| native_name | String | Optional | The native name of this PURL component in the package ecosystem. For instance, the 'namespace' for the 'maven' type is 'groupId', and 'scope' for the 'npm' PURL type. |
| note | String | Optional | Extra note text. |
Location: /namespace_definition/requirement
Property: requirement (Required)
Type: String
States that the PURL namespace component is optional, required or prohibited for a PURL type.
Shall be one of:
Type: String
Constant: optional
States that this PURL component is optional for a PURL type.
Type: String
Constant: required
States that this PURL component is required for a PURL type.
Type: String
Constant: prohibited
States that this PURL component is prohibited for a PURL type.
Location: /namespace_definition/registered_values
Property: registered_values (Optional)
Type: Array
Optional set of registered namespace values for this PURL type. If the namespace value for a PURL of this type is not one of these registered values, a tool should report a warning. The registered namespace values should be sorted lexicographically.
Location: /namespace_definition/registered_values/value
Property: value
Type: String
Registered namespace value for this PURL type.
Location: /namespace_definition/registered_values/description
Property: description
Type: String
Explanation of what this namespace value means for this PURL type.
Location: /namespace_definition/registered_values/reference_url
Property: reference_url
Type: String
Optional Reference URL for where this namespace value is defined for this PURL type.
Location: /namespace_definition/permitted_characters
Property: permitted_characters (Optional)
Type: String
Format: A regular expression dialect defined by
A regular expression defining the 'permitted characters' for this component of this Package-URL type. If provided, this shall be a subset of the '
Location: /namespace_definition/case_sensitive
Property: case_sensitive (Optional)
Type: Boolean
Default Value: true
true if this PURL component is case-sensitive. If false, the form shall be
Location: /namespace_definition/normalization_rules
Property: normalization_rules (Optional)
Type: array (of String)
List of rules to normalize this component for this PURL type. These are plain text, unstructured rules as some require programming and cannot be enforced only with a schema. Tools are expected to apply these rules programmatically. Each item of this array shall be a string.
All items shall be unique.
Location: /namespace_definition/native_name
Property: native_name (Optional)
Type: String
The native name of this PURL component in the package ecosystem. For instance, the 'namespace' for the 'maven' type is 'groupId', and 'scope' for the 'npm' PURL type.
Location: /namespace_definition/note
Property: note (Optional)
Type: String
Extra note text.
Location: /name_definition
Property: name_definition (Required)
Type: Object
Definition of the name component for this PURL type. The PURL name component is required for all PURL type definitions.
| Property | Type | Requirement | Description |
|---|---|---|---|
| requirement | Array | Required | States that the PURL name component is always required. |
| permitted_characters | String | Optional | A regular expression ( |
| case_sensitive | Boolean | Optional | true if this PURL component is case-sensitive. If false, the form shall be |
| normalization_rules | Array | Optional | List of rules to normalize this component for this PURL type. These are plain text, unstructured rules as some require programming and cannot be enforced only with a schema. Tools are expected to apply these rules programmatically. |
| native_name | String | Optional | The native name of this PURL component in the package ecosystem. For instance, the 'namespace' for the 'maven' type is 'groupId', and 'scope' for the 'npm' PURL type. |
| note | String | Optional | Extra note text. |
Location: /name_definition/requirement
Property: requirement (Required)
Type: String
States that the PURL name component is always required.
Shall be one of:
Type: String
Constant: required
States that this PURL component is required for a PURL type.
Location: /name_definition/permitted_characters
Property: permitted_characters (Optional)
Type: String
Format: A regular expression dialect defined by
A regular expression defining the 'permitted characters' for this component of this Package-URL type. If provided, this shall be a subset of the '
Location: /name_definition/case_sensitive
Property: case_sensitive (Optional)
Type: Boolean
Default Value: true
true if this PURL component is case-sensitive. If false, the form shall be
Location: /name_definition/normalization_rules
Property: normalization_rules (Optional)
Type: array (of String)
List of rules to normalize this component for this PURL type. These are plain text, unstructured rules as some require programming and cannot be enforced only with a schema. Tools are expected to apply these rules programmatically. Each item of this array shall be a string.
All items shall be unique.
Location: /name_definition/native_name
Property: native_name (Optional)
Type: String
The native name of this PURL component in the package ecosystem. For instance, the 'namespace' for the 'maven' type is 'groupId', and 'scope' for the 'npm' PURL type.
Location: /name_definition/note
Property: note (Optional)
Type: String
Extra note text.
Location: /version_definition
Property: version_definition (Optional)
Type: Object
Definition of the version component for this PURL type. The PURL version component is optional for a specific PURL type definition.
| Property | Type | Requirement | Description |
|---|---|---|---|
| requirement | Array | Required | States that the PURL version is optional. |
| permitted_characters | String | Optional | A regular expression ( |
| case_sensitive | Boolean | Optional | true if this PURL component is case-sensitive. If false, the form shall be |
| normalization_rules | Array | Optional | List of rules to normalize this component for this PURL type. These are plain text, unstructured rules as some require programming and cannot be enforced only with a schema. Tools are expected to apply these rules programmatically. |
| native_name | String | Optional | The native name of this PURL component in the package ecosystem. For instance, the 'namespace' for the 'maven' type is 'groupId', and 'scope' for the 'npm' PURL type. |
| note | String | Optional | Extra note text. |
Location: /version_definition/requirement
Property: requirement (Required)
Type: String
States that the PURL version is optional.
Shall be one of:
Type: String
Constant: optional
States that this PURL component is optional for a PURL type.
Location: /version_definition/permitted_characters
Property: permitted_characters (Optional)
Type: String
Format: A regular expression dialect defined by
A regular expression defining the 'permitted characters' for this component of this Package-URL type. If provided, this shall be a subset of the '
Location: /version_definition/case_sensitive
Property: case_sensitive (Optional)
Type: Boolean
Default Value: true
true if this PURL component is case-sensitive. If false, the form shall be
Location: /version_definition/normalization_rules
Property: normalization_rules (Optional)
Type: array (of String)
List of rules to normalize this component for this PURL type. These are plain text, unstructured rules as some require programming and cannot be enforced only with a schema. Tools are expected to apply these rules programmatically. Each item of this array shall be a string.
All items shall be unique.
Location: /version_definition/native_name
Property: native_name (Optional)
Type: String
The native name of this PURL component in the package ecosystem. For instance, the 'namespace' for the 'maven' type is 'groupId', and 'scope' for the 'npm' PURL type.
Location: /version_definition/note
Property: note (Optional)
Type: String
Extra note text.
Location: /qualifiers_definition
Property: qualifiers_definition (Optional)
Type: Array
Definition of the qualifiers specific to this PURL type. The PURL qualifiers component is optional for a specific PURL type, but a qualifiers key or keys may be required for a specific PURL type. Each item of this array shall be a Qualifiers definition object.
Location: /qualifiers_definition/[]
Type: Object
The definition of a qualifier specific to this PURL type.
| Property | Type | Requirement | Description |
|---|---|---|---|
| key | String | Required | The key for the qualifier. |
| requirement | Array | Optional | States that a PURL qualifier key is optional, recommended or required for a PURL type. |
| description | String | Required | The description of this qualifier. |
| default_value | String | Optional | The optional default value of this qualifier if not provided. |
| native_name | String | Optional | The equivalent native name for this qualifier key. |
Location: /qualifiers_definition/key
Type: String
The key for the qualifier.
Location: /qualifiers_definition/requirement
Type: String
States that a PURL qualifier key is optional, recommended or required for a PURL type.
Shall be one of:
Type: String
Constant: optional
States that this PURL component is optional for a PURL type.
Type: String
Constant: recommended
States that this PURL component is recommended for a PURL type.
Type: String
Constant: required
States that this PURL component is required for a PURL type.
Location: /qualifiers_definition/description
Type: String
The description of this qualifier.
Location: /qualifiers_definition/default_value
Type: String
The optional default value of this qualifier if not provided.
Location: /qualifiers_definition/native_name
Type: String
The equivalent native name for this qualifier key.
All items shall be unique.
Location: /subpath_definition
Property: subpath_definition (Optional)
Type: Object
The definition for the subpath for this PURL type. The PURL subpath component is optional for a specific PURL type definition.
| Property | Type | Requirement | Description |
|---|---|---|---|
| requirement | Array | Required | States that the PURL subpath is optional. |
| permitted_characters | String | Optional | A regular expression ( |
| case_sensitive | Boolean | Optional | true if this PURL component is case-sensitive. If false, the form shall be |
| normalization_rules | Array | Optional | List of rules to normalize this component for this PURL type. These are plain text, unstructured rules as some require programming and cannot be enforced only with a schema. Tools are expected to apply these rules programmatically. |
| native_name | String | Optional | The native name of this PURL component in the package ecosystem. For instance, the 'namespace' for the 'maven' type is 'groupId', and 'scope' for the 'npm' PURL type. |
| note | String | Optional | Extra note text. |
Location: /subpath_definition/requirement
Property: requirement (Required)
Type: String
States that the PURL subpath is optional.
Shall be one of:
Type: String
Constant: optional
States that this PURL component is optional for a PURL type.
Location: /subpath_definition/permitted_characters
Property: permitted_characters (Optional)
Type: String
Format: A regular expression dialect defined by
A regular expression defining the 'permitted characters' for this component of this Package-URL type. If provided, this shall be a subset of the '
Location: /subpath_definition/case_sensitive
Property: case_sensitive (Optional)
Type: Boolean
Default Value: true
true if this PURL component is case-sensitive. If false, the form shall be
Location: /subpath_definition/normalization_rules
Property: normalization_rules (Optional)
Type: array (of String)
List of rules to normalize this component for this PURL type. These are plain text, unstructured rules as some require programming and cannot be enforced only with a schema. Tools are expected to apply these rules programmatically. Each item of this array shall be a string.
All items shall be unique.
Location: /subpath_definition/native_name
Property: native_name (Optional)
Type: String
The native name of this PURL component in the package ecosystem. For instance, the 'namespace' for the 'maven' type is 'groupId', and 'scope' for the 'npm' PURL type.
Location: /subpath_definition/note
Property: note (Optional)
Type: String
Extra note text.
Location: /examples
Property: examples (Required)
Type: array (of String)
Pattern Constraint: ^pkg:[a-z][a-z0-9-\.]+/.*$
Example of valid PURLs for this package type. Each item of this array shall be a string.
All items shall be unique.
Location: /note
Property: note (Optional)
Type: String
Note about this PURL type.
Location: /reference_urls
Property: reference_urls (Optional)
Type: array (of String)
Format:
Optional list of informational reference URLs about this PURL type. Each item of this array shall be a string.
All items shall be unique.
This Annex provides a copy of the current Package-URL Type Definition Schema. The format is JSON Schema version draft-07.
The schema shown below is available in electronic form at: https://www.packageurl.org/purl-schemas/purl-type-definition.schema-1.1.json
{
"$schema": "https://json-schema.org/draft-07/schema#",
"$id": "https://packageurl.org/purl-schemas/purl-type-definition.schema-1.1.json",
"title": "Package-URL Type Definition",
"description": "Schema to specify a Package-URL (PURL) type as a structured definition.",
"type": "object",
"additionalProperties": false,
"definitions": {
"optional_requirement": {
"title": "Component optional requirement",
"description": "States that this PURL component is optional for a PURL type.",
"type": "string",
"const": "optional"
},
"recommended_requirement": {
"title": "Component recommended requirement",
"description": "States that this PURL component is recommended for a PURL type.",
"type": "string",
"const": "recommended"
},
"required_requirement": {
"title": "Component required requirement",
"description": "States that this PURL component is required for a PURL type.",
"type": "string",
"const": "required"
},
"prohibited_requirement": {
"title": "Component prohibited requirement",
"description": "States that this PURL component is prohibited for a PURL type.",
"type": "string",
"const": "prohibited"
},
"purl_component_definition": {
"title": "PURL component definition",
"description": "PURL component definition properties that apply to most PURL components",
"type": "object",
"properties": {
"permitted_characters": {
"title": "Permitted characters in this PURL component",
"description": "A regular expression (ECMA-262 dialect) defining the 'permitted characters' for this component of this Package-URL type. If provided, this shall be a subset of the 'Permitted characters' defined in this Standard.",
"type": "string",
"format": "regex"
},
"case_sensitive": {
"title": "Case sensitive",
"description": "true if this PURL component is case sensitive. If false, the form shall be lowercase.",
"type": "boolean",
"default": true
},
"normalization_rules": {
"title": "Normalization rules",
"description": "List of rules to normalize this component for this PURL type. These are plain text, unstructured rules as some require programming and cannot be enforced only with a schema. Tools are expected to apply these rules programmatically.",
"type": "array",
"uniqueItems": true,
"items": {
"type": "string"
}
},
"native_name": {
"title": "Native name",
"description": "The native name of this PURL component in the package ecosystem. For instance, the 'namespace' for the 'maven' type is 'groupId', and 'scope' for the 'npm' PURL type.",
"type": "string"
},
"note": {
"title": "Note",
"description": "Extra note text.",
"type": "string"
}
}
}
},
"required": [
"$id",
"type",
"type_name",
"description",
"repository",
"namespace_definition",
"name_definition",
"examples"
],
"properties": {
"$schema": {
"title": "JSON schema",
"description": "Contains the URL of the JSON schema for Package-URL type definition.",
"const": "https://packageurl.org/purl-schemas/purl-type-definition.schema-1.1.json",
"format": "uri"
},
"$id": {
"title": "PURL type definition id",
"description": "The unique identifier URI for this PURL type definition.",
"type": "string",
"pattern": "^https:\\/\\/packageurl\\.org/purl-types/[a-z0-9-]+-definition\\.json$"
},
"type": {
"title": "PURL type",
"description": "The type string for this Package-URL type.",
"type": "string",
"pattern": "^[a-z][a-z0-9-\\.]+$",
"examples": [
"maven",
"npm",
"pypi"
]
},
"type_name": {
"title": "Type name",
"description": "The name for this PURL type.",
"type": "string",
"examples": [
"Apache Maven",
"Python Package"
]
},
"description": {
"title": "Description",
"description": "The description of this PURL type.",
"type": "string"
},
"repository": {
"title": "Repository",
"description": "The package repository usage for this PURL type.",
"type": "object",
"additionalProperties": false,
"required": [
"use_repository"
],
"properties": {
"use_repository": {
"title": "Use repository",
"description": "true if this PURL type uses a public package repository.",
"type": "boolean",
"default": false
},
"default_repository_url": {
"title": "Default repository URL",
"description": "The default public repository URL for this PURL type",
"type": "string",
"format": "uri"
},
"note": {
"title": "Note",
"description": "Extra note text.",
"type": "string"
}
}
},
"namespace_definition": {
"title": "Namespace definition",
"description": "Definition of the namespace component for this PURL type. The PURL namespace component shall be required, optional or prohibited for a specific PURL type definition.",
"type": "object",
"required": [
"requirement"
],
"properties": {
"requirement": {
"title": "Namespace requirement",
"description": "States that the PURL namespace component is optional, required or prohibited for a PURL type.",
"type": "string",
"oneOf": [
{
"$ref": "#/definitions/optional_requirement"
},
{
"$ref": "#/definitions/required_requirement"
},
{
"$ref": "#/definitions/prohibited_requirement"
}
]
},
"registered_values": {
"title": "Registered namespace values",
"description": "Optional set of registered namespace values for this PURL type. If the namespace value for a PURL of this type is not one of these registered values, a tool should report a warning. The registered namespace values should be sorted lexicographically.",
"type": "array",
"uniqueItems": true,
"minItems": 1,
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"value",
"description"
],
"properties": {
"value": {
"title": "Registered Namespace Value",
"description": "Registered namespace value for this PURL type.",
"type": "string"
},
"description": {
"title": "Registered Namespace Description",
"description": "Explanation of what this namespace value means for this PURL type.",
"type": "string"
},
"reference_url": {
"title": "Reference URL",
"description": "Optional Reference URL for where this namespace value is defined for this PURL type.",
"type":"string"
}
}
}
}
},
"allOf": [
{
"$ref": "#/definitions/purl_component_definition"
}
]
},
"name_definition": {
"title": "Name definition",
"description": "Definition of the name component for this PURL type. The PURL name component is required for all PURL type definitions.",
"type": "object",
"required": [
"requirement"
],
"properties": {
"requirement": {
"title": "Name component requirement",
"description": "States that the PURL name component is always required.",
"type": "string",
"oneOf": [
{
"$ref": "#/definitions/required_requirement"
}
]
}
},
"allOf": [
{
"$ref": "#/definitions/purl_component_definition"
}
]
},
"version_definition": {
"title": "Version definition",
"description": "Definition of the version component for this PURL type. The PURL version component is optional for a specific PURL type definition.",
"type": "object",
"required": [
"requirement"
],
"properties": {
"requirement": {
"title": "Version requirement",
"description": "States that the PURL version is optional.",
"type": "string",
"oneOf": [
{
"$ref": "#/definitions/optional_requirement"
}
]
}
},
"allOf": [
{
"$ref": "#/definitions/purl_component_definition"
}
]
},
"qualifiers_definition": {
"title": "Qualifiers definition",
"description": "Definition of the qualifiers specific to this PURL type. The PURL qualifiers component is optional for a specific PURL type, but a qualifiers key or keys may be required for a specific PURL type.",
"type": "array",
"additionalItems": false,
"uniqueItems": true,
"items": {
"title": "Qualifiers definition",
"description": "The definition of a qualifier specific to this PURL type.",
"type": "object",
"additionalProperties": false,
"required": [
"key",
"description"
],
"properties": {
"key": {
"title": "Qualifier key",
"description": "The key for the qualifier.",
"type": "string"
},
"requirement": {
"title": "Qualifier key requirement",
"description": "States that a PURL qualifier key is optional, recommended or required for a PURL type.",
"type": "string",
"oneOf": [
{
"$ref": "#/definitions/optional_requirement"
},
{
"$ref": "#/definitions/recommended_requirement"
},
{
"$ref": "#/definitions/required_requirement"
}
]
},
"description": {
"title": "Description",
"description": "The description of this qualifier key.",
"type": "string"
},
"default_value": {
"title": "Default value",
"description": "The optional default value of this qualifier if not provided.",
"type": "string"
},
"native_name": {
"title": "Native name",
"description": "The equivalent native name for this qualifier key.",
"type": "string"
}
}
}
},
"subpath_definition": {
"title": "Subpath definition",
"description": "The definition for the subpath for this PURL type. The PURL subpath component is optional for a specific PURL type definition.",
"type": "object",
"required": [
"requirement"
],
"properties": {
"requirement": {
"title": "Subpath requirement",
"description": "States that the PURL subpath is optional.",
"type": "string",
"oneOf": [
{
"$ref": "#/definitions/optional_requirement"
}
]
}
},
"allOf": [
{
"$ref": "#/definitions/purl_component_definition"
}
]
},
"examples": {
"title": "PURL examples",
"description": "Example of valid PURLs for this package type.",
"type": "array",
"uniqueItems": true,
"minItems": 1,
"items": {
"type": "string",
"pattern": "^pkg:[a-z][a-z0-9-\\.]+/.*$"
}
},
"note": {
"title": "Note",
"description": "Note about this PURL type.",
"type": "string"
},
"reference_urls": {
"title": "Reference URLs",
"description": "Optional list of informational reference URLs about this PURL type.",
"type": "array",
"uniqueItems": true,
"items": {
"type": "string",
"format": "uri"
}
}
}
}
This Annex documents standard PURL qualifiers that may be used across many PURL type definitions.
The PURL qualifiers component provides flexibility to define important PURL information at the PURL type level. This flexibility is provided by key=value pairs. It may be tempting to use many key=value pairs to document many package attributes, but their usage should be limited to the minimal set of key=value pairs that are necessary for accurate package identification or location. This restraint is necessary to ensure that PURLs stay compact and human-readable.
Tools that build PURLs should sort multiple qualifiers lexicographically by key, but this is not expected behaviour for a tool to parse or validate a PURL.
The standards for the PURL qualifiers component and the key=value pairs are defined in two ECMA-427 clauses:
Many qualifiers are applicable to multiple PURL types. These qualifiers should be used according to the following definitions.
| key | Definition |
|---|---|
| checksum | One or more checksums stored as a comma-separated list |
| download_url | A URL for a direct package download URL |
| file_name | The file name of a package archive |
| repository_url | A URL for a package or software repository |
| vcs_url | A URL for a version control system (VCS) location |
| vers | A |
Each item in the value for a 'checksum' qualifier is in the form of 'lowercase_algorithm:hex_encoded_lowercase_value' such as 'sha1:ad9503c3e994a4f611a4892f2e67ac82df727086'. Multiple 'checksum' values are separated by an encoded comma ('%2C').
The following standard 'checksum' keys should be used where applicable. This is not an exclusive list.
| algorithm | key | used by |
|---|---|---|
| BLAKE2b-256 | blake2b-256 | pypi |
| BLAKE3 | blake3 | |
| MD5 | md5 | maven, pypi |
| RIPEMD-160 | ripemd160 | |
| SHAKE256 | shake256 | |
| SHA1 | sha1 | maven, npm |
| SHA2-224 | sha224 | |
| SHA2-256 | sha256 | cargo, gem, maven, npm |
| SHA2-384 | sha384 | npm |
| SHA2-512 | sha512 | npm, nuget |
| SHA3-224 | sha3-224 | |
| SHA3-256 | sha3-256 | |
| SHA3-384 | sha3-384 | |
| SHA3-512 | sha3-512 |
pkg:generic/openssl@1.1.10g?checksum=sha1:ad9503c3e994a4f%2Csha256:41bf9088b3a1e6c1ef1d
Most package managers provide a mechanism to derive a 'download-url' from PURL data. Use this qualifier for use cases where the download URL for a package cannot be derived from the PURL or otherwise provided by the package manager. A 'download_url' value shall be
pkg:generic/openssl@1.1.10g?download_url=https:%2F%2Fopenssl.org%2Fsource%2Fopenssl-1.1.0g.tar.gz
This qualifier is intended for the use case where you need to specify the name of a package archive or other file. Use the subpath component for the use case where you need to specify a PURL at the file level.
pkg:pypi/django@1.11.1?file_name=Django-1.11.1.tar.gz
pkg:pypi/django@1.11.1?file_name=Django-1.11.1-py2.py3-none-any.whl
This qualifieris intended for the use cases where:
type definition,
type.
A 'repository_url' value shall be
pkg:bazel/curl@8.8.0?repository_url=https:%2F%2Fexample.org%2Fbazel-registry
pkg:huggingface/microsoft/deberta-v3-base@559062ad13d311b87b2c455e67dcd5f1c8f65111?repository_url=https:%2F%2Fhub-ci.huggingface.co
pkg:maven/groovy/groovy@1.0?repository_url=https:%2F%2Fmaven.google.com
This qualifier is intended for the use case where you need to specify a PURL at its Version Control System location. The syntax for 'vcs_url' is based on Python pip syntax at: https://pip.pypa.io/en/stable/topics/vcs-support/ The syntax is:
<vcs_tool>+<transport>://<host_name>[/<path_to_repository>][@<revision_tag_or_branch>]#<sub_path>]
This compact VCS location notation supports referencing locations in version control systems such as Git, Mercurial, Subversion and Bazaar, and specifies the type of VCS tool using url prefixes: 'git+', 'hg+', 'bzr+', 'svn+' and specific transport schemes such as SSH or HTTPS.
Using usernames and password in the host_name is not supported and should be reported by tools as an error.
Specifying sub-paths, branch names, a commit hash, a revision or a tag name is recommended, and supported, using the '@' delimiter for a commit version and the '#' delimiter for a sub-path.
In VCS location compact notations, the trailing slashes in host_name, and path_to_repository are not significant. Leading and trailing slashes in sub_path are not significant.
A 'vcs_url' value shall be
pkg:generic/bitwarden?vcs_url=git%2Bhttps:%2F%2Fgit.fsfe.org%2Fdxtr%2Fbitwarden%40cc55108da32
pkg:npm/mypackage@12.4.5?vcs_url=git:%2F%2Fhost.com%2F%2Fpath%2Fto%2Frepo.git%404345abcd34343
The primary use cases for this qualifier are to identify a version range for dependency analysis or vulnerability reporting. Use of this qualifier is mutually exclusive with use of the version component. The value for a 'vers' key shall adhere to the Version Range Specification.
pkg:pypi/django?vers=vers:pypi%2F%3E%3D1.11.0%7C%21%3D1.11.1%7C%3C2.0.0
This Annex documents the Augmented Backus-Naur Form (
A valid PURL string adheres to the following grammar with the syntax defined according to
PURL = scheme ":" type
[ "/" namespace ] "/" name
[ "@" version ] [ "?" qualifiers ] [ "#" subpath ]
; --- structure ---
scheme = %x70.6B.67 ; constant with the value "pkg" (lowercase only)
type = alpha-lc *( alpha-lc / DIGIT / "." / "-" )
namespace = namespace-segment *( "/" namespace-segment )
namespace-segment = 1*pchar-ns
name = 1*pchar
version = 1*pchar
qualifiers = qualifier *( "&" qualifier )
qualifier = qualifier-key "=" qualifier-value
qualifier-key = alpha-lc *( alpha-lc / DIGIT / "." / "-" / "_" )
qualifier-value = 1*pchar
subpath = subpath-segment *( "/" subpath-segment )
subpath-segment = subpath-segment-sc *pchar-ns ; no leading "."
/ "." subpath-segment-sc *pchar-ns ; forbid segment "."
/ ".." 1*pchar-ns ; forbid segment ".."
; excludes the exact segments "." and ".."
subpath-segment-sc = ( alphanumeric
/ "-" / "_" / "~"
/ colon ) ; = `unreserved` without "."
/ pct-encoded-ns
; safe characters
; --- character classes ---
alpha-lc = %x61-7A ; lowercase a-z
alphanumeric = ALPHA / DIGIT
punctuation = "." / "-" / "_" / "~"
separator = ":" / "/" / "@" / "?" / "=" / "&" / "#"
colon = ":"
percent = "%"
unreserved = alphanumeric / punctuation / colon
reserved = "/" / "@" / "?" / "=" / "&" / "#"
; `reserved` and `separator` are not referenced directly;
; listed to document characters that require percent-encoding
pchar = unreserved / pct-encoded
pchar-ns = unreserved / pct-encoded-ns
; `-ns` suffix = variant that forbids the percent-encoded slash ("%2F")
; --- percent-encoding ---
pct-encoded = pct-encoded-ns / percent "2" "F"
pct-encoded-ns = percent (
( "0" / "1" ) HEXDIG
; %00-1F
/ "2" ( DIGIT / "A" / "B" / "C" )
; %20-2F except %2D ("-") and %2E (".") and %2F ("/")
/ "3" ( "B" / "C" / "D" / "E" / "F" )
; %30-3F except %30-39 (0-9) and %3A (":")
/ "4" "0"
; %40-4F except %41-4F (A-O)
/ "5" ( "B" / "C" / "D" / "E" )
; %50-5F except %50-5A (P-Z) and %5F ("_")
/ "6" "0"
; %60-6F except %61-6F (a-o)
/ "7" ( "B" / "C" / "D" / "F" )
; %70-7F except %70-7A (p-z) and %7E ("~")
/ ( "8" / "9" / "A" / "B" / "C" / "D" / "E" / "F" ) HEXDIG
; %80-FF
)
Conformance to this grammar for valid PURL strings is necessary but not sufficient because the following constraints of this Standard are not expressible in
This Standard is authored on GitHub in a plaintext source format called Ecmarkup. Ecmarkup is an HTML and Markdown dialect that provides a framework and toolset for authoring ECMA specifications in plaintext and processing the specification into a full-featured HTML rendering that follows the editorial conventions for this document. Ecmarkup builds on and integrates a number of other formats and technologies including Grammarkdown for defining syntax and Ecmarkdown for authoring algorithm steps. PDF renderings of this Standard are produced using a print stylesheet which takes advantage of the CSS Paged Media specification and is converted using PrinceXML.
We extend our gratitude to TC39 for their exceptional work in developing Ecmarkup, which has greatly facilitated TC54's successful adoption of this tool for the preparation and maintenance of our technical specifications.
Ecma International
Rue du Rhone 114
CH-1204 Geneva
Tel: +41 22 849 6000
Fax: +41 22 849 6001
Web: https://ecma-international.org/
© 2026 Ecma International
This draft document may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published, and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this section are included on all such copies and derivative works. However, this document itself may not be modified in any way, including by removing the copyright notice or references to Ecma International, except as needed for the purpose of developing any document or deliverable produced by Ecma International.
This disclaimer is valid only prior to final version of this document. After approval all rights on the standard are reserved by Ecma International.
The limited permissions are granted through the standardization phase and will not be revoked by Ecma International or its successors or assigns during this time.
This document and the information contained herein is provided on an "AS IS" basis and ECMA INTERNATIONAL DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY OWNERSHIP RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.