Attest tools · PDF readability check

Check PDF columns and reading order

Inspect a synthetic two-column PDF for column layout and reading-order findings.

1 credit per successful call

Input JSON

{
  "file_base64": "PDF file, 1.5 KB, base64 in the real request"
}

Captured output JSON

{
  "profile": "general",
  "pages": 1,
  "findings": [
    {
      "id": "text_layer_present",
      "level": "ok",
      "message": "Every page analysed has selectable text: 48 words across 1 page(s)."
    },
    {
      "id": "fonts_not_embedded",
      "level": "warning",
      "message": "1 of 1 font(s) are not carried inside the file, or could not be read from it, so a reader substitutes a local font. Substitution changes line breaks and, with some encodings, the characters that come out of a copy-and-paste."
    },
    {
      "id": "multi_column_layout",
      "level": "warning",
      "message": "1 page(s) are laid out in 2 columns, measured as a blank vertical band 223.2 points wide with text on both sides. Readers that take the text in the order the file draws it can interleave the columns, so a sidebar ends up mixed into the main text. A right-aligned column of dates is not counted here."
    },
    {
      "id": "reading_order_ok",
      "level": "ok",
      "message": "The text is drawn in the order it is read on the page."
    },
    {
      "id": "untagged_pdf",
      "level": "warning",
      "message": "The file carries no tag tree, so software has to infer headings, lists and reading order from where the marks sit on the page."
    },
    {
      "id": "no_language_metadata",
      "level": "warning",
      "message": "The file does not declare a language. Screen readers and some text processors fall back to a default, which affects pronunciation and hyphenation."
    }
  ],
  "stats": {
    "document": {
      "pdf_version": "1.7",
      "page_count": 1,
      "pages_analyzed": 1,
      "pages_failed": 0,
      "analysis_truncated": null,
      "words": 48,
      "characters": 208,
      "text_items": 16,
      "text_layer": "full",
      "text_selectable": true,
      "average_text_coverage": 0.073,
      "pages_without_text": 0,
      "image_only_pages": 0,
      "images": 0,
      "image_streams": 0,
      "images_over_pixel_cap": 0,
      "largest_image_pixels": 0,
      "streams": 3,
      "largest_stream_decompressed_bytes": 1766,
      "analyzed_decompressed_bytes": 1892,
      "unmeasured_streams": 0,
      "fonts": [
        {
          "name": "Helvetica",
          "embedded": false,
          "type3": false
        }
      ],
      "fonts_embedded": 0,
      "fonts_not_embedded": 1,
      "encrypted": false,
      "encryption_filter": null,
      "permissions": null,
      "acroform": false,
      "xfa": false,
      "signatures": false,
      "linearized": false,
      "tagged": false,
      "language": null,
      "pdfa_claim": {
        "claimed": false,
        "part": null,
        "conformance": null
      },
      "pdfua_claim": {
        "claimed": false,
        "part": null
      },
      "links": {
        "annotations": 0,
        "text_urls": 0
      },
      "multi_column_pages": 1,
      "table_pages": 0,
      "rotated_text_items": 0,
      "page_sizes": 1
    },
    "pages": [
      {
        "number": 1,
        "width_pt": 595.3,
        "height_pt": 841.9,
        "rotation": 0,
        "characters": 208,
        "words": 48,
        "lines": 16,
        "text_items": 16,
        "text_coverage": 0.073,
        "columns": 2,
        "column_gutter_pt": 223.2,
        "images": 0,
        "image_area_ratio": 0,
        "image_only": false,
        "link_annotations": 0,
        "reading_order": {
          "transitions": 15,
          "backward_jumps": 0,
          "column_switches": 1,
          "sane": true
        },
        "tables": {
          "horizontal_rules": 0,
          "vertical_rules": 0,
          "ruled_grid": false,
          "aligned_rows": 0,
          "aligned_columns": 0,
          "likely": false
        },
        "parse_failed": false
      }
    ]
  },
  "limits": {
    "inline_file_bytes": 3145728,
    "fetched_file_bytes": 8388608,
    "pages_analyzed": 30,
    "image_pixels": 40000000,
    "stream_decompressed_bytes": 4194304,
    "analyzed_decompressed_bytes": 31457280,
    "decompressed_budget_applies_to": "the largest single stream, and the heaviest 30 streams together",
    "profile_scan_characters": 200000
  },
  "sources": [
    {
      "name": "Mozilla pdf.js (npm pdfjs-dist 6.3.289), Apache License 2.0",
      "url": "https://github.com/mozilla/pdf.js",
      "used_for": "parsing the file: text runs and their positions, fonts, images, paths, annotations, metadata and permission flags"
    },
    {
      "name": "ISO 32000-1:2008, Document management — Portable Document Format — Part 1: PDF 1.7",
      "url": "https://www.iso.org/standard/51502.html",
      "used_for": "the file-structure terms used in this report: header, encryption dictionary, permission flags, XFA forms, tagged structure tree"
    },
    {
      "name": "ISO 19005 (PDF/A) identification schema, read from the file's own XMP metadata",
      "url": "https://www.pdfa.org/resource/iso-19005-pdfa/",
      "used_for": "pdfa_claim — reported as the file's own claim, not as a validation result"
    }
  ],
  "notice": "General guidance about how automated readers see this file. Attest does not speak for any specific applicant-tracking system.",
  "checked_at": "2026-10-20T20:47:49.615Z"
}

API call

curl -s -X POST https://getattest.com.au/api/v1/pdf/inspect \
  -H "authorization: Bearer $ATTEST_API_KEY" \
  -H "content-type: application/json" \
  --data-binary @request.json

Run this call with your own bearer key. Save the complete input as request.json, replacing file descriptions with your own base64 file content and any truncated text with the full text. Issue an API key.

About this example

The input was validated and run locally through the registered service. The output above is a display preview of the captured service result. File bytes are described instead of printed, and strings longer than 400 characters are truncated; the HTTP API also adds call_id, credits_charged and credits_remaining. Timestamps and generated identifiers will vary.

Source: apps/api/svc/pdf_inspect.mjs

Tool reference and limits · API key guide