Decode an AIPM 1.2 URL
Paste any AIPM 1.2 URL to decode it without visiting the display page. Useful when the primary site is unavailable, for archival verification, or when you prefer a local decode.
Archived copy of this page: web.archive.org — AIPM 1.2 decode page
Paste AIPM URL
Decoder options
Copy this script and run it with any Python 3.x installation. No external dependencies — standard library only. This is the most durable decode method.
#!/usr/bin/env python3
"""
AIPM 1.2 URL decoder — stdlib only, no external dependencies.
Specification: https://aipmq.org/1.2/spec/
Usage:
python3 aipm_decode.py 'https://aipmq.org/1.2/aipm/#v=1.2&...'
python3 aipm_decode.py # paste URL when prompted
"""
import sys, json, zlib, base64
from urllib.parse import urlparse, parse_qs
FIELD_LABELS = {
'v': 'AIPM version',
'role': 'Human role',
'model': 'AI model',
'ctx': 'Context / prompt',
'date': 'Date',
'show': 'Show mode',
'src': 'Content URL',
'hs': 'Content hash (SHA)',
'type': 'Content type',
'doc': 'Full Context Document URL',
'hd': 'Document hash (SHA)',
'author': 'Author',
'org': 'Organization',
'lang': 'Language',
'prev': 'Previous mark URL',
'qr': 'QR only (qr=0 = URL only)',
}
def decode_aipm_url(url: str) -> dict:
"""Parse an AIPM URL and return its metadata fields."""
fragment = urlparse(url.strip()).fragment
if not fragment:
raise ValueError("No hash fragment found in URL. "
"AIPM metadata lives after the '#' character.")
params = parse_qs(fragment, keep_blank_values=True)
get = lambda k: params.get(k, [None])[0]
z = get('z')
if z:
# Decompress deflate-raw + base64url payload (AIPM 1.1+)
b64 = z.replace('-', '+').replace('_', '/')
b64 += '=' * (-len(b64) % 4) # restore base64 padding
raw = base64.b64decode(b64)
# wbits=-15 → raw DEFLATE (RFC 1951), no zlib/gzip wrapper
return json.loads(zlib.decompress(raw, wbits=-15))
else:
# Plain params (human-readable, no compression)
fields = ['v', 'role', 'model', 'ctx', 'date', 'show',
'src', 'hs', 'type', 'doc', 'hd',
'author', 'org', 'lang', 'prev', 'qr']
return {k: get(k) for k in fields if get(k) is not None}
def main():
if len(sys.argv) > 1:
url = ' '.join(sys.argv[1:])
else:
url = input('Paste AIPM URL: ').strip()
data = decode_aipm_url(url)
print()
max_label = max((len(FIELD_LABELS.get(k, k)) for k in data), default=10)
for k, v in data.items():
label = FIELD_LABELS.get(k, k)
print(f' {label:<{max_label}} : {v}')
print()
if __name__ == '__main__':
main()
An AIPM URL encodes its metadata in the hash fragment — the part after
#. The fragment never reaches the server, so all metadata is visible in the
URL itself.
Plain URL (no compression)
If the URL contains readable parameters after #, decode each key=value pair:
| v | AIPM version (e.g. 1.2) |
| role | Human role: all, wrote, prompted+reviewed, prompted+edited, prompted, edited, reviewed, supervised, automated |
| model | AI model or system name |
| ctx | Context / prompt description (URL-decoded) |
| date | ISO 8601 date or datetime |
| show | 1 = show role abbreviation on QR mark |
| src | Link to the content this mark applies to |
| hs | SHA hash of the content file — W3C SRI format (sha256-… or sha384-…) |
| type | Content type: text, code, image, audio, video, multimodal |
| doc | Link to the Full Context Document |
| hd | SHA hash of the Full Context Document — W3C SRI format |
| author | Human creator name |
| org | Organization |
| lang | BCP 47 language tag (e.g. en, fr) |
| prev | URL of previous AIPM mark — creates a provenance chain |
| qr | 0 = URL-only mode (no QR possible — payload too large) |
Compressed URL (z= parameter)
If the URL fragment starts with z=, the metadata is compressed.
The z value is a raw DEFLATE (RFC 1951, no zlib wrapper)
compressed JSON object, encoded in base64url (no padding).
To decode in a terminal (Python 3 standard library):
python3 -c "
import sys, json, zlib, base64
z = input('Paste z= value: ')
b64 = z.replace('-','+').replace('_','/')
b64 += '=' * (-len(b64) % 4)
raw = base64.b64decode(b64)
print(json.dumps(json.loads(zlib.decompress(raw, wbits=-15)), indent=2))
"
The resulting JSON contains the same field names as the plain-URL table above.
Paste your AIPM URL in the box above, then click the button below. Pyodide will load on first use (~10MB download).
If aipmq.org becomes unavailable, these archived copies of this decode page
can be used instead:
-
Internet Archive (Wayback Machine):
web.archive.org/web/*/https://aipmq.org/1.2/decode/
Choose the most recent snapshot. -
Software Heritage (source code archive):
When the AIPM GitHub repository is live, it will also be archived automatically at softwareheritage.org.
The Python snippet tab gives you a fully offline, domain-independent decoder you can save and run anywhere — no network, no browser, no dependencies beyond Python 3.6's standard library. It is the most resilient long-term option; keep a local copy if you need guaranteed offline decode capability.