{"id":50277861,"url":"https://github.com/imsweb/django-chromepdf","last_synced_at":"2026-05-27T22:02:12.246Z","repository":{"id":54184052,"uuid":"300323739","full_name":"imsweb/django-chromepdf","owner":"imsweb","description":"Generate PDFs from HTML using Chrome and Selenium.","archived":false,"fork":false,"pushed_at":"2024-11-04T14:57:18.000Z","size":302,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-09-14T14:03:00.288Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/imsweb.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-10-01T15:14:31.000Z","updated_at":"2024-11-04T14:56:31.000Z","dependencies_parsed_at":"2023-11-22T20:24:00.733Z","dependency_job_id":"3104eab0-94c7-4c89-9a00-2d45ec685c7b","html_url":"https://github.com/imsweb/django-chromepdf","commit_stats":{"total_commits":110,"total_committers":3,"mean_commits":"36.666666666666664","dds":"0.18181818181818177","last_synced_commit":"c78dcb977ab8d0408681119b8176e0776b2bd088"},"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"purl":"pkg:github/imsweb/django-chromepdf","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imsweb%2Fdjango-chromepdf","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imsweb%2Fdjango-chromepdf/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imsweb%2Fdjango-chromepdf/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imsweb%2Fdjango-chromepdf/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/imsweb","download_url":"https://codeload.github.com/imsweb/django-chromepdf/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imsweb%2Fdjango-chromepdf/sbom","scorecard":{"id":486463,"data":{"date":"2025-08-11","repo":{"name":"github.com/imsweb/django-chromepdf","commit":"4ea05c46c4f4cb45dd6543bcba794764cc9f1863"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2,"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":"Code-Review","score":0,"reason":"Found 0/28 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":"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":"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":"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":"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":"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":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: BSD 3-Clause \"New\" or \"Revised\" 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":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"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"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 4 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"23 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: PYSEC-2024-102 / GHSA-5hgc-2vfp-mqvc","Warn: Project is vulnerable to: PYSEC-2024-68 / GHSA-795c-9xpc-xw6g","Warn: Project is vulnerable to: PYSEC-2023-225 / GHSA-7h4p-27mh-hmrw","Warn: Project is vulnerable to: PYSEC-2025-47 / GHSA-7xr5-9hcq-chf9","Warn: Project is vulnerable to: PYSEC-2024-156 / GHSA-8498-2h75-472j","Warn: Project is vulnerable to: PYSEC-2025-37 / GHSA-8j24-cjrq-gr2m","Warn: Project is vulnerable to: PYSEC-2024-58 / GHSA-9jmf-237g-qf46","Warn: Project is vulnerable to: PYSEC-2024-59 / GHSA-f6f8-9mx6-9mx2","Warn: Project is vulnerable to: PYSEC-2023-226 / GHSA-h8gc-pgj2-vjm3","Warn: Project is vulnerable to: PYSEC-2023-100 / GHSA-jh3w-4vvf-mjgr","Warn: Project is vulnerable to: PYSEC-2024-67 / GHSA-jh75-99hh-qvx9","Warn: Project is vulnerable to: PYSEC-2024-157 / GHSA-m9g8-fxxm-xg86","Warn: Project is vulnerable to: PYSEC-2025-13 / GHSA-p3fp-8748-vqfq","Warn: Project is vulnerable to: PYSEC-2024-70 / GHSA-pv4p-cwwg-4rph","Warn: Project is vulnerable to: PYSEC-2025-1 / GHSA-qcgg-j2x8-h9g8","Warn: Project is vulnerable to: PYSEC-2024-56 / GHSA-qg2p-9jwr-mmqf","Warn: Project is vulnerable to: PYSEC-2023-222 / GHSA-qmf9-6jqf-j8fq","Warn: Project is vulnerable to: PYSEC-2023-61 / GHSA-r3xc-prgr-mg9p","Warn: Project is vulnerable to: PYSEC-2024-69 / GHSA-r836-hh6v-rg5g","Warn: Project is vulnerable to: GHSA-rrqc-c2jx-6jgv","Warn: Project is vulnerable to: PYSEC-2024-47 / GHSA-vm8q-m57g-pff3","Warn: Project is vulnerable to: PYSEC-2024-57 / GHSA-x7q2-wr7g-xqmf","Warn: Project is vulnerable to: PYSEC-2024-28 / GHSA-xxj9-f6rv-m3x4"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-19T17:56:57.110Z","repository_id":54184052,"created_at":"2025-08-19T17:56:57.111Z","updated_at":"2025-08-19T17:56:57.111Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33585203,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-27T02:00:06.184Z","response_time":53,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":[],"created_at":"2026-05-27T22:02:11.393Z","updated_at":"2026-05-27T22:02:12.241Z","avatar_url":"https://github.com/imsweb.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ChromePDF\n\n## Overview\n\nChromePDF is a small Python 3 library that uses [Selenium](https://pypi.org/project/selenium/) and Google Chrome to convert HTML into a PDF. This is accomplished by using Chrome's `Page.printToPDF` DevTools command.\n\nChromePDF provides a function that accepts an html string, plus a dict of page parameters, and other settings, and returns the bytes containing a PDF:\n\n```\npdf_bytes = generate_pdf(html_string, pdf_kwargs, **kwargs)\n```\n\nAs of version 1.4, ChromePDF can also be run from the command line.\n\n```\npython -m chromepdf generate-pdf --chrome-path=/usr/bin/google-chrome path/to/input.html path/to/output.pdf\n```\n\nBecause it renders via Chrome, it supports a wide range of CSS and HTML tags that should display the same as if you used Chrome to view the HTML itself.\n\nChromePDF can take advantage of [Django](https://pypi.org/project/Django/) settings for configuration, but Django is not a required dependency.\n\nOfficial ChromePDF releases [are available on PyPI](https://pypi.org/project/django-chromepdf/).\n\n## Installation\n\n**1. Install ChromePDF via pip.**\n\nThe latest version can be installed via PyPI. This will also install Selenium, the only direct dependency (Selenium versions 3 and 4 are supported; 3 will be used if already present, otherwise will install 4). \n\nYou may view the [Changelog](CHANGELOG.md) for a list of all ChromePDF version changes. ChromePDF uses [semantic versioning](https://semver.org/) for its release numbering. You are encouraged to pin your requirements to a Major.Minor version in a manner that will also receive Bugfix updates like so:\n```\npip install django-chromepdf~=1.7.4\n```\n\n**2. Set the location of your Chrome executable.** This can be done in one of two ways:\n\n* In your Django settings, set `CHROMEPDF['CHROME_PATH']` to the full path of the executable (E.G., `r'C:\\Program Files (x86)\\Google\\...\\chrome.exe'`)\n* OR, pass `chrome_path` as a keyword argument to the `generate_pdf()` function.\n\n## About Chromedrivers\n\nA chromedriver executable is necessary to interface between Selenium and Chrome. ChromePDF will automatically check the version of your Chrome binary and download the required chromedriver [from the Chrome website](https://chromedriver.chromium.org/downloads) if it doesn't exist, into your `site-packages/chromepdf/chromedrivers/` folder. If the Chrome binary ever gets upgraded, ChromePDF will realize this and download the required driver for it.\n\nYou may disable these automatic downloads in the following way:\n* In your Django settings, set `CHROMEPDF['CHROMEDRIVER_DOWNLOADS']` to False\n* OR, pass a `chromedriver_downloads=False` argument to `generate_pdf()`\n\nYou may also specify a chromedriver path manually. This is recommended if you disable downloads:\n* In your Django settings, set `CHROMEPDF['CHROMEDRIVER_PATH']` to the full path of the executable (E.G., `r'C:\\Users\\myuser\\...\\chromedriver_win32\\chromedriver.exe'`)\n* OR, pass a `chromedriver_path` argument to `generate_pdf()` containing the path.\n* OR, if both of the above are not set, and you've disabled downloads, and if your chromedriver is in your `PATH` environment variable, then Selenium should be able to find it automatically.\n\n## Example: `generate_pdf()`\nNote: `generate_pdf()` cannot include external files including CSS. You must include all your CSS within `\u003cstyle\u003e` tags or as inline styles.\n\n```python\n# NOTE: This example assumes that you've set Django's settings.CHROMEPDF['CHROME_PATH'] = '(path to your Chrome instance)'\nfrom chromepdf import generate_pdf \n\nwith open('myfile.html','r') as f:\n    html_string = f.read()\n             \npdf_kwargs = {\n    'paperFormat': 'A4',\n    'marginTop': '2.5cm',\n    'marginLeft': '2cm',\n    'marginRight': '2cm',\n    'marginBottom': '3.5cm',\n    'displayHeaderFooter': True,\n    'headerTemplate': '',\n    'footerTemplate': '''\n        \u003cdiv style='font-size: 12px; width: 100%; padding: 0; padding-left: 2cm; padding-bottom: 1cm; margin: 0; '\u003e\n            Page \u003cspan class='pageNumber'\u003e\u003c/span\u003e of \u003cspan class='totalPages'\u003e\u003c/span\u003e\n        \u003c/div\u003e\n    ''',\n}\npdf_bytes = generate_pdf(html_string, pdf_kwargs)\n\nwith open('myfile.pdf', 'wb') as file:\n    file.write(pdf_bytes)\n```\n\n## Example: Command-Line Usage\nChromePDF can generate PDFs from the command-line. This method will not rely on Django settings. Example syntax:\n```\n# Convert file.html into file.pdf and place in the same directory\npython -m chromepdf generate-pdf path/to/file.html [kwargs]\n\n# Convert file.html and place the output PDF file at a specific path.\npython -m chromepdf generate-pdf path/to/file.html path/to/output.pdf [kwargs]\n```\nKeyword arguments for command-line usage are almost identical to `generate_pdf()` keyword arguments:\n```\n--chrome-path=path/to/google-chrome\n--chromedriver-path=path/to/chromedriver\n--chromedriver-downloads=0 # 0 or 1\n--chrome-args=\"--arg1 --arg2\" # Always use quotes to avoid misinterpreting as commands. \n--pdf-kwargs-json=path/to/file.json # JSON file containing a dict of values to pass to pdf_kwargs\n```\nThe recommended usage is to pass a `--chrome-path`, and let ChromePDF handle the chromedriver downloads automatically.\n```\npython -m chromepdf generate-pdf --chrome-path=/usr/bin/google-chrome path/to/file.html path/to/output.pdf\n```\nThe command will have a return code of zero on success, and nonzero on failure.\n\n## Django Settings\n\nYou can specify default settings in your Django settings file, if desired, via a `CHROMEPDF` settings. Anything passed via the `pdf_kwargs` argument will override the `PDF_KWARGS` settings.\n```python\n# settings.__init__.py\n\nCHROMEPDF = {\n    'CHROME_PATH': r'C:\\Program Files (x86)\\Google\\...\\chrome.exe',\n    'CHROME_ARGS': [], # Optional list of command-line argument strings to pass to Chrome when rendering a PDF.\n    'CHROMEDRIVER_PATH': None, # will rely on downloads instead\n    'CHROMEDRIVER_DOWNLOADS': True, # automatically download the correct chromedriver for the chrome path\n    'PDF_KWARGS': {\n        'paperFormat': 'A4',\n        'marginTop': '2.5cm',\n        'marginLeft': '2cm',\n        'marginRight': '2cm',\n        'marginBottom': '3.5cm',\n    }\n}\n```\n\n\n## PDF_KWARGS Options\n\nThe `pdf_kwargs` argument to `generate_pdf()` lets you specify all the arguments for Chrome's `Page.printToPDF` API. Its API can be viewed here:\n\n[Page.printToPDF API](https://chromedevtools.github.io/devtools-protocol/1-3/Page/#method-printToPDF) (url is funky. If you get a 404, try reloading/refreshing)\n\nSome shortcut parameters are provided by `generate_pdf()` for convenience. Here is a list of all the options:\n\nLayout:\n*  **scale**: Scale of the PDF. Default `1`.\n*  **landscape**: `True` to use landscape mode. Default `False`.\n\nPage Dimensions:\n*  **paperWidth**: Width of the paper, in inches. Can also use some CSS string values, like `'30cm'`. Default: `8.5`\n*  **paperHeight**: Height of the paper, in inches. Can also use some CSS string values, like `'30cm'`. Default: `11`\n*  **paperFormat**: A string indicating a paper size format, such as `'letter'` or `'A4'`. Case-insensitive. This will override `paperWidth` and `paperHeight`. Not part of `Page.printToPDF` API.  Provided for convenience.\n\nContent:\n*  **displayHeaderFooter**: `True` to display header and footer. Default `False`.\n*  **headerTemplate**: HTML containing the header for all pages. Default is an empty string. You may pass html tags with specific classes in order to insert values. For example, `\u003cspan class='title'\u003e\u003c/span\u003e` would insert the the title.\n   * date: formatted print date \n   * title: document title \n   * url: document location \n   * pageNumber: current page number \n   * totalPages: total pages in the document \n* **footerTemplate**: HTML containing the footer for all pages. Default is an empty string. You may pass html tags with specific classes in order to insert values (same as above)\n* **printBackground**: `True` to print background graphics. Default `False`.\n\nMargins:\n*  **margin**: Shortcut used to set all four margin values at once. Not part of `Page.printToPDF` API.  Provided for convenience.\n*  **marginTop**: Top margin. Default: `'1cm'`\n*  **marginBottom**: Bottom margin. Default: `'1cm'`\n*  **marginLeft**: Left margin. Default: `'1cm'`\n*  **marginRight**: Right margin. Default: `'1cm'`\n\nPage Ranges:\n*  **pageRanges**: String indicating page ranges to use. Example: `'1-5, 8, 11-13'`\n*  **ignoreInvalidPageRanges**: If `True`, will silently ignore invalid 'pageRanges' values. Default `False`.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fimsweb%2Fdjango-chromepdf","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fimsweb%2Fdjango-chromepdf","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fimsweb%2Fdjango-chromepdf/lists"}