{"id":13827696,"url":"https://github.com/kiwi0fruit/pyppdf","last_synced_at":"2026-03-01T19:01:45.418Z","repository":{"id":49802454,"uuid":"166063513","full_name":"kiwi0fruit/pyppdf","owner":"kiwi0fruit","description":"Pyppeteer PDF. Print html sites and files to pdf via pyppeteer (uses patched pyppeteer that by default downloads updated Chromium revision via https with certifi).","archived":false,"fork":false,"pushed_at":"2020-10-18T15:31:19.000Z","size":258,"stargazers_count":38,"open_issues_count":6,"forks_count":6,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-26T02:41:55.828Z","etag":null,"topics":["html-to-pdf","html2pdf","pdf","puppeteer","pyppeteer","python"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kiwi0fruit.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-01-16T15:30:18.000Z","updated_at":"2025-09-22T11:26:32.000Z","dependencies_parsed_at":"2022-09-15T06:11:47.402Z","dependency_job_id":null,"html_url":"https://github.com/kiwi0fruit/pyppdf","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"purl":"pkg:github/kiwi0fruit/pyppdf","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kiwi0fruit%2Fpyppdf","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kiwi0fruit%2Fpyppdf/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kiwi0fruit%2Fpyppdf/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kiwi0fruit%2Fpyppdf/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kiwi0fruit","download_url":"https://codeload.github.com/kiwi0fruit/pyppdf/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kiwi0fruit%2Fpyppdf/sbom","scorecard":{"id":562066,"data":{"date":"2025-08-11","repo":{"name":"github.com/kiwi0fruit/pyppdf","commit":"f25fb02691caf7be5abbdbae658c350121877b64"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-20T13:59:51.666Z","repository_id":49802454,"created_at":"2025-08-20T13:59:51.666Z","updated_at":"2025-08-20T13:59:51.666Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29980792,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-01T16:35:47.903Z","status":"ssl_error","status_checked_at":"2026-03-01T16:35:44.899Z","response_time":124,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["html-to-pdf","html2pdf","pdf","puppeteer","pyppeteer","python"],"created_at":"2024-08-04T09:02:05.567Z","updated_at":"2026-03-01T19:01:45.400Z","avatar_url":"https://github.com/kiwi0fruit.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"# pyppdf: Pyppeteer PDF\n\n[![Build Status](https://travis-ci.org/kiwi0fruit/pyppdf.svg?branch=master)](https://travis-ci.org/kiwi0fruit/pyppdf)\n\nPrints html sites and files to pdf via pyppeteer (uses patched pyppeteer that by default downloads updated Chromium revision via https with certifi). I use it with  [Pandoctools/Knitty](https://github.com/kiwi0fruit/pandoctools).\n\nPyppeteer is a Python port of the Puppeteer. pyppdf command line interface is built with the help of [litereval](https://github.com/kiwi0fruit/litereval) and click.\n\nAt the moment recommended settings when reading from stdin are following:\n\n```bash\necho \"# Header\nText \\$f(x)=x^2\\$\" |\npandoc -f markdown -t html --standalone --self-contained |\npyppdf -o doc.pdf --goto temp\n```\n\n\n# Contents:\n\n* [Install](#install)\n* [CLI](#cli)\n  * [pyppdf](#pyppdf)\n  * [pyppdf-install](#pyppdf-install)\n* [Python API](#python-api)\n\n\n# Install\n\nNeeds python 3.6+\n\n### conda install:\n\n```bash\nconda install -c defaults -c conda-forge pyppdf\n```\n\n### pip install:\n\n```bash\npip install pyppdf\n```\n\n### Linux\n\nIf on Ubuntu additionally install ([Chrome headless doesn't launch on Unix](https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md#chrome-headless-doesnt-launch-on-unix)):\n\n```bash\nsudo apt-get update\nsudo apt-get install -y ca-certificates fonts-liberation libappindicator3-1 libasound2 libatk-bridge2.0-0 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgbm1 libgcc1 libglib2.0-0 libgtk-3-0 libnspr4 libnss3 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 lsb-release wget xdg-utils\n```\n\n\n# CLI\n\n### pyppdf\n\nCommand line interface:\n\n```\nUsage: pyppdf [OPTIONS] [PAGE]\n\n  Reads html document, converts it to pdf via pyppeteer and writes to disk\n  (or writes base64 encoded pdf to stdout).\n\n  PAGE is an URL or a common file path, pyppdf reads from stdin if PAGE is\n  not set.\n\n  -a, --args defaults:\n\n  {launch={args=['--font-render-hinting=none']},goto={waitUntil='networkidle0',\n  timeout=100000}, pdf={width='8.27in', printBackground=True, margin={top='1in',\n  right='1in', bottom='1in', left='1in'},}}\n\n  They affect the following pyppeteer methods (only the last name should be\n  used):  pyppeteer.launch, page.goto, page.emulateMedia,\n  page.waitForNavigation, page.waitFor, page.pdf. See:\n\n  https://pyppeteer.github.io/pyppeteer/reference.html#pyppeteer.page.Page.pdf\n\nOptions:\n  -a, --args TEXT  Python code str that would be evaluated to the dictionary\n                   that is a pyppeteer functions options. Has predefined\n                   defaults.\n  -u, --upd TEXT   Same as --args dict but --upd dict is recursively merged\n                   into --args.\n  -o, --out TEXT   Output file path. If not set then pyppdf writes base64\n                   encoded pdf to stdout.\n  -d, --dir TEXT   Directory for '--goto temp' mode. Has priority over dir of\n                   the --out\n\n  -g, --goto [url|setContent|temp|data-text-html]\n                   Choose page.goto behaviour. By default pyppdf tries 'url'\n                   mode then 'setContent' mode. 'url' works only if url (PAGE)\n                   arg was provided or {goto={url=\u003c...\u003e}} was set in the merged\n                   args. 'setContent' (works without page.goto), 'temp' (temp\n                   file) and 'data-text-html' work only with stdin input.\n                   'setContent' and 'data-text-html' presumably do not support\n                   some remote content. I have bugs with the last one\n                   when: page.goto(f'data:text/html,{html}')\n  --help           Show this message and exit.\n\n```\n\nSee [Pyppeteer methods](https://miyakogi.github.io/pyppeteer/reference.html#pyppeteer.page.Page.pdf).\n\n\n### pyppdf-install\n\nSimply downloads and installs Chromium beforehead (uses fresher revision from pyppdf):\n\n```bash\npyppdf-install\n```\n\n\n# Python API\n\n```\ndef save_pdf(output_file: str=None, url: str=None, html: str=None,\n             args_dict: Union[str, dict]=None,\n             args_upd: Union[str, dict]=None,\n             goto: str=None, dir_: str=None) -\u003e bytes:\n    \"\"\"\n    Converts html document to pdf via pyppeteer\n    and writes to disk if asked. Also returns bytes of pdf.\n\n    ``args_dict`` affect the following methods that are used during\n    conversion (only the last name should be used):\n    ``pyppeteer.launch``, ``page.goto``, ``page.emulateMedia``,\n    ``page.waitForNavigation``, ``page.waitFor``, ``page.pdf``. See:\n     https://pyppeteer.github.io/pyppeteer/reference.html#pyppeteer.page.Page.pdf\n\n    ``args_dict`` default value:\n\n    \u003e\u003e\u003e # {launch={args=['--font-render-hinting=none']},\n    \u003e\u003e\u003e #  goto={waitUntil='networkidle0', timeout=100000},\n    \u003e\u003e\u003e #  pdf={width='8.27in', printBackground=True,\n    \u003e\u003e\u003e #       margin={top='1in', right='1in',\n    \u003e\u003e\u003e #               bottom='1in', left='1in'},}}\n    \u003e\u003e\u003e #\n\n    ``args_upd`` examples that won't overwrite other options:\n\n    * ``\"{launch={args=['--no-sandbox', '--disable-setuid-sandbox']}}``\n    *  ``\"{emulateMedia=\"screen\", waitFor=1000}\"``\n\n    Formats for **values** of the ``args_dict``:\n    ``*args`` and ``**kwargs`` for functions:\n\n    * ``{(): (arg1, arg2), kwarg1=val1, kwarg2=val2}``\n      Special key for positional args,\n    * ``[arg1, arg2]`` or ``(arg1, arg2)`` Positional only,\n    * If value in the **root**  ``args_dict`` is None\n      (like ``{foo=None}``) it later means that ``'foo'`` key is not used\n      (same as if it was absent in the **root** dict).\n\n    Parameters\n    ----------\n    output_file :\n        Path to write pdf to.\n    url :\n        Page URL address or html document file path\n        (url has priority over html).\n    html :\n        html document file source\n        (url has priority over html).\n    args_dict :\n        Options that govern conversion.\n        dict with pyppeteer kwargs or Python code str that would\n        be \"litereval\" evaluated to the dictionary.\n        If None then default values are used.\n        Supports extended dict syntax: {foo=100, bar='yes'}.\n    args_upd :\n        dict with *additional* pyppeteer kwargs or Python code str\n        that would be \"litereval\" evaluated to the dictionary.\n        This dict would be recursively merged into args_dict.\n    goto :\n        Same as in 'main' function.\n    dir_ :\n        Directory for goto temp mode.\n    \"\"\"\n```\n\n```py\nasync def main(args: dict, url: str=None, html: str=None, output_file: str=None,\n               goto: str=None, dir_: str=None) -\u003e bytes:\n    \"\"\"\n    Returns bytes of pdf.\n\n    Parameters\n    ----------\n    args :\n        Pyppeteer options that govern conversion.\n        dict with keys dedicated for pyppeteer functions used.\n        See save_pdf for more details.\n    url :\n        Site address or html document file path (url - that by the\n        way can also be set in args - has priority over html).\n    html :\n        html document file source\n    output_file :\n        Path to save pdf\n    goto :\n        One of:\n        \u003e\u003e\u003e # ('url', 'setContent', 'temp', 'data-text-html')\n        \u003e\u003e\u003e #\n        \u003e\u003e\u003e # Choose page.goto behaviour. By default pyppdf tries 'url' mode\n        \u003e\u003e\u003e # then 'setContent' mode. 'url' works only if url (PAGE) arg was\n        \u003e\u003e\u003e # provided or {goto={url=\u003c...\u003e}} was set in the merged args.\n        \u003e\u003e\u003e # 'setContent' (works without page.goto), 'temp' (temp file) and\n        \u003e\u003e\u003e # 'data-text-html' work only with stdin input. 'setContent' and\n        \u003e\u003e\u003e # 'data-text-html' presumably do not support some remote\n        \u003e\u003e\u003e # content. I have bugs with the last one when:\n        \u003e\u003e\u003e # page.goto(f'data:text/html,{html}')\n        \u003e\u003e\u003e #\n    dir_ :\n        Directory for goto temp mode.\n    \"\"\"\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkiwi0fruit%2Fpyppdf","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkiwi0fruit%2Fpyppdf","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkiwi0fruit%2Fpyppdf/lists"}