Archive
TR

Case analysis. Published

Does a black bar remove the information from a PDF?

The black bar covered it, the PDF kept it

Civio and the PDF Association were the first to write about the text left in this contract's bookmarks. This file downloads the historical copy linked from Civio's article again on 14 October 2026, reads it with two PDF libraries and runs a controlled experiment.

CSINT-CASE-2026-020Open in archive

Paragraph (b) from page 14 of the contract. After the words To the extent that the total Cost of Goods exceed, a black bar runs to the end of the line. The second line also opens with a black bar and goes on with AstraZeneca shall provide an updated purchase. Three more black bars close the paragraph.
1684 × 432 pixels
Page 14 of the historical copy, paragraph (b). The image was drawn from the PDF itself with PyMuPDF at 4x scale; it is not a screenshot. The contract text belongs to the European Commission and AstraZeneca; the image is drawn from the historical copy. Source, DocumentCloud, historical copy

Page 14 of the historical copy, paragraph (b)

What the records show
The words 870 million Euros, absent from the page text, stand in three bookmark titles of the same file, and all three lead to page 14. Two separate libraries gave the same counts.
What they do not show
The text under the black bars. A final total that was paid. Who produced the copy, and by what process.
Based on
The DocumentCloud copy linked from Civio: 1,025,010 bytes, SHA-256 beginning 3c79a5de. Downloaded on 14 October 2026 and read locally with PyMuPDF 1.27.2.3 and pypdf 6.10.0.

The record examined

On 29 January 2021 the European Commission published its advance purchase agreement with AstraZeneca with some passages covered by black bars. The same day Civio linked to a copy of the contract. The question is whether text about the covered passages stayed in another part of the file.

Method

The copy was downloaded and its size and SHA-256 recorded. The page text and bookmark titles were read with PyMuPDF 1.27.2.3, and the same counts were repeated with pypdf 6.10.0. The original, a resaved-only control copy and an experiment copy with the bookmark list emptied were then compared on all 41 pages. No file was uploaded to an online service.

Which copy

The file examined is the DocumentCloud copy linked from Civio's article of 29 January 2021. The PDF the Commission publishes today is a separate, different file; it does not stand in for the historical copy.

Recorded SHA-256 values and the download response

logs/preserved-evidence-manifest.json
  "sources\\apa-civio-documentcloud.pdf": "3c79a5dea75766d9efd7d2516927eae16a4211abde70a84ba966a84ba0ecc9d1",
  "sources\\apa_astrazeneca-current.pdf": "08be8ba71d9fd7b9adcdcf02d00bfd58910f4a02e8541989ffbe977d0c7a0ccd",

sources/apa-civio-documentcloud-download.json
  "url": "https://s3.documentcloud.org/documents/20466651/apa_-_astrazenecapdf.pdf",
  "download_utc": "2026-10-14T16:38:43.0531989Z",
  "status": 200,
    "Content-Length": [
      "1025010"
    ],
    "Last-Modified": [
      "Fri, 29 Jan 2021 15:05:36 GMT"
The lines are taken as they are from the record files; the other response headers in between are not shown. Last-Modified is the date the server reports, not the date the document was made. DocumentCloud, historical copy
Historical copyCurrent official PDF
Size1,025,010 bytes3,094,193 bytes
SHA-256 begins3c79a5de08be8ba7
Pages4142
Bookmark titles2540
Extracted page text88,517 characters0 characters
Read with PyMuPDF 1.27.2.3. The creator field in the current file's properties carries a Canon device name. These measurements do not show who made the difference between the two files, or why.

Test 1: the page text

The text area of page 14. Ten lines of black bars at the top, then paragraphs (b), (c) and (d). In (b) the bars follow Cost of Goods exceed, in (c) six short bars follow reasonably expected to exceed, and in (d) five lines of bars follow is less.
1880 × 2008 pixels
The text area of page 14, drawn the same way. According to PyMuPDF the page holds no image; the black areas are 28 filled drawings. The contract text belongs to the European Commission and AstraZeneca; the image is drawn from the historical copy. Source, DocumentCloud, historical copy

The text area of page 14, drawn the same way

Pages readObserved
41
Text extractedObserved
88,517 characters
Pages whose text contains 870Observed
0
The byte string 870 in page 14's decompressed content streamObserved
0 matches
Selecting and copying paragraph (b) in the viewerObserved
292 characters, no 870
Not finding the bytes does not prove the information was fully removed; the same information can sit in another encoding.

PyMuPDF, text of page 14, lines 16 to 41 (analysis/page14-text.txt)

(b) To the extent that the total Cost of Goods exceed 
 
, AstraZeneca shall provide an updated purchase 
and payment schedule to the Commission, which shall state the delivery schedule 
of the Initial Europe Doses and the corresponding amounts payable by the 
Participating Member States, 
 
 
   
(c) If AstraZeneca becomes aware that the estimated Cost of Goods are 
reasonably expected to exceed 
 
 
 
 
 
 then 
AstraZeneca shall notify the Commission of such excess and provide the relevant 
evidence in this respect. Following such notice, AstraZeneca and the Commission 
shall agree to a payment or other mechanism which will result in AstraZeneca 
supplying the Participating Member States with a number of Doses without 
incurring a loss. Such mechanism may include a reduction in the number of Doses 
and/or a further increase in Price Per Dose. 
(d) If following the finalization of the matters contemplated hereby, documentary 
evidence provided by AstraZeneca indicates that the Cost of Goods for the Initial 
Europe Doses sold is less 
Where the black bars are, the extracted text keeps empty lines. After the word exceed the text goes on with a comma.

Test 2: the bookmarks

The historical copy open in a desktop PDF viewer. The toolbar reads 14 of 41. On the left a Table of Contents panel shows (b) with the estimated amount of 870 million Euros by less than 20% and (c) with expected to exceed 870 million Euros by 20% or more. On the right the same page shows paragraphs (b) and (c) with black bars.
1360 × 1200 pixels
A frame from the screen recording, 14 October 2026. The empty grey area on the right was cropped. The marks sit only over lines in the recording. The contract text belongs to the European Commission and AstraZeneca; the frame comes from a screen recording of the document open in a desktop viewer. Source, DocumentCloud, historical copy

A frame from the screen recording, 14 October 2026

Object 465, its /Dest and /Title fields as read with PyMuPDF (analysis/object-465.txt)

<<
  /Dest [ 48 0 R /XYZ 69 599 0 ]
  /Next 464 0 R
  /Parent 457 0 R
  /Prev 458 0 R
  /Title (\(b\) To the extent that the total Cost of Goods exceed the estimated amount of 870 million Euros by less than 20%, AstraZeneca shall provide an updated purchase and payment schedule to the Commission, which shall state the delivery schedule of the Init...)
>>
The title ends with three dots in the file itself; the shortening is the file's own. The 48 in /Dest is the object number of page 14.
ObjectWording in the title/DestPage
465(b) exceed the estimated amount of 870 million Euros by less than 20%48 0 R /XYZ 69 59914
464(c) reasonably expected to exceed 870 million Euros by 20% or more48 0 R /XYZ 69 49014
459(d) for the Initial Europe Doses sold is less than 870 million Euros48 0 R /XYZ 69 36814
The three of the 254 bookmark titles that contain 870. The wording is taken from the titles as it is. All three targets are on the same page object, from top to bottom in the order (b), (c) and (d).

In the page text, paragraph (b) breaks off at the word exceed and goes on with a comma. The bookmark title that leads to the same paragraph reads the estimated amount of 870 million Euros by less than 20% at that point. This shows the two texts belong to the same paragraph. It does not show exactly what is written under the black bars.

The wording in the bookmark is a condition about an estimated cost. It is not a final total that was paid.

A second library

pypdf 6.10.0, historical copy (analysis/pypdf-verification.json, selected lines)

  "tool": "pypdf",
  "version": "6.10.0",
    "historical": {
      "pages": 41,
      "bookmarks": 254,
          "xref": 465,
          "destination": "[IndirectObject(48, 0, 2501813762624), '/XYZ', 69, 599, 0]"
          "xref": 464,
          "destination": "[IndirectObject(48, 0, 2501813762624), '/XYZ', 69, 490, 0]"
          "xref": 459,
          "destination": "[IndirectObject(48, 0, 2501813762624), '/XYZ', 69, 368, 0]"
      "page_text_870_hits": [],
The title lines and the page list are left out to save space; the lines keep the file's order. pypdf found the same three objects, the same page object and no match in the page text.

The two libraries differ on one count: pypdf counts 77 annotations, while PyMuPDF's per-page annotation list is empty. A further check explains it: there are 76 links and 1 form field, and that PyMuPDF list leaves out both kinds. There is no contradiction, but the file cannot be said to have no annotations.

Controlled experiment

Three files were compared. A is the downloaded original, never changed. B is a copy of A only resaved with pypdf. C is a copy of A resaved with its bookmark list removed. B and C were made for this experiment; they are not historical publisher versions.

A, originalB, resavedC, list empty
Pages on reopening414141
Active bookmarks2542540
Bookmark titles with 870330
Image size, against Aitself41/41 same41/41 same
Raw RGB pixel SHA-256, against Aitself41/41 same41/41 same
Extracted text, against Aitself41/41 same41/41 same
PDF file bytes, against Aitselfdifferentdifferent
Cost-bearing /Title objects3: 459, 464, 4653: 550, 551, 5523: 550, 551, 552
Reachable from the file's traileryesyesno
Image and pixel measurements with PyMuPDF 1.27.2.3, text equality and object reachability with pypdf 6.10.0. Each library compared its own output with itself.

The operations behind copy C (analysis/comparison/creation.json)

      "file": "EXPERIMENT-outlines-removed.pdf",
      "role": "experiment: outline deletion plus unreferenced-object cleanup",
      "operations": [
        "clone_document_from_reader(original)",
        "root_object.pop('/Outlines')",
        "compress_identical_objects(remove_duplicates=False, remove_unreferenced=True)",
        "write(new_file)"
      ],
      "bytes": 1107111,
      "sha256": "6bed75bf6cdb11192db05bce7601f14848b1e6c2a9860df85fbc10f9d5b02f37",
      "reopened_pages": 41,
      "catalog_has_outlines": false

Title objects left in copy C, pypdf (analysis/comparison/independent-verification.json)

    "outlines_removed_experiment": {
      "pages": 41,
      "outline_count": 0,
      "page_text_870_count": 0,
      "residual_titles": [
          "xref": 550,
          "title_contains_870": true,
          "reachable_from_trailer": false
          "xref": 551,
          "title_contains_870": true,
          "reachable_from_trailer": false
          "xref": 552,
          "title_contains_870": true,
          "reachable_from_trailer": false
The list of page text hashes and the bracket lines are left out to save space. In C the list is empty, yet the three Title objects with the cost remain in the file, detached. C is not a safe redaction recipe, nor a cleaned document.

What to check before sharing

A PDF's page can look clean. The page text, the bookmarks, the document properties and the attachments are separate parts of the file, and each needs its own look. In this copy the wording about the cost was in the bookmarks.

PartRead in the historical copy
Page text41 pages, 88,517 characters, no 870
Bookmarks254 titles, three with 870 million Euros
Document propertiesTitle, author, creator, producer and date fields empty; XMP data 0 characters
Attachments0
Read with PyMuPDF 1.27.2.3. An empty field does not show that the file holds no other hidden data.

What we found and what we did not

FoundNot found
No 870 in the page text; 870 million Euros in three bookmark titles.We did not open the text under the black bars or recover deleted page text.
All three titles point to page 14; two libraries gave the same result.We found no final total that was paid; the wording is a condition about an estimated cost.
With the list emptied, the three title objects stayed in the file, detached.We did not find who produced the copy or by what process.

What the evidence does not show

  • The bookmark wording is a condition about an estimated cost, not a final total that was paid.
  • We did not recover deleted page text. We did not open the text under the black areas.
  • These measurements do not prove who produced the historical copy or by what process.
  • The copy's authenticity depends on a third-party source chain.
  • The document was not uploaded to an online service; it was examined locally with PyMuPDF 1.27.2.3 and pypdf 6.10.0.

Working record. Before sharing a PDF, look past the page into the file's other parts. Write down which copy you read.

Video

Sources

Published by Ahmet Göker. Agent and tool contributions shown in the records are listed under Working record. Documents, images and photographs remain with their owners. People are not shown or are blurred.