# Convert SEC Filings to PDF With Python > Python examples for the PDF Generator API. Convert any SEC EDGAR filing or exhibit into a PDF with the sec-api Python package, preserving the original formatting, images and tables. Source: https://sec-api.io/docs/sec-filings-to-pdf-generator-api/python-example The examples below use the `sec-api` Python package to convert any SEC filing or exhibit into a PDF. The original formatting is preserved, including images and tables, and inline XBRL tags are stripped to keep the file size down. To download a file as filed, without converting it, see the [Download API Python example](https://sec-api.io/docs/edgar-file-and-sec-filings-download-api/python-example). ## Installation Install the package with pip: ``` pip install sec-api ``` ## Download a 10-K as PDF `get_pdf` takes the sec.gov URL of the filing and returns the PDF as bytes, so the file is written in binary mode. The example converts Apple's annual report. ```python from sec_api import PdfGeneratorApi pdfGeneratorApi = PdfGeneratorApi("YOUR_API_KEY") url = "https://www.sec.gov/Archives/edgar/data/320193/000032019323000106/aapl-20230930.htm" pdf = pdfGeneratorApi.get_pdf(url) with open("apple-10-k.pdf", "wb") as f: f.write(pdf) ``` ## Download a prospectus as PDF Prospectuses filed on Forms 424B2, 424B3, 424B4 and S-1 run to hundreds of pages, with the offering terms, financial statements and risk factors laid out in tables. The example converts a Rule 424(b)(4) prospectus of roughly four megabytes. ```python from sec_api import PdfGeneratorApi pdfGeneratorApi = PdfGeneratorApi("YOUR_API_KEY") # Form 424B4, a Rule 424(b)(4) prospectus url = "https://www.sec.gov/Archives/edgar/data/2109823/000121390026101599/ea0286599-08.htm" pdf = pdfGeneratorApi.get_pdf(url) with open("prospectus.pdf", "wb") as f: f.write(pdf) ``` ## Download a proxy statement as PDF Proxy statements on Form DEF 14A are image heavy: logos, performance graphs, director photographs and the proxy voting card. Every image the filing references is rendered into the PDF, which is also why a DEF 14A takes longer to convert than a press release. ```python from sec_api import PdfGeneratorApi pdfGeneratorApi = PdfGeneratorApi("YOUR_API_KEY") # Form DEF 14A, Apple's 2026 proxy statement url = "https://www.sec.gov/Archives/edgar/data/320193/000130817926000008/aapl014016-def14a.htm" pdf = pdfGeneratorApi.get_pdf(url) with open("apple-def-14a.pdf", "wb") as f: f.write(pdf) ``` ## Convert an exhibit to PDF Exhibits work the same way. The example converts the Exhibit 99.1 press release attached to Apple's Q3 2026 earnings 8-K. Exhibit URLs are listed in the `documentFormatFiles` array returned by the [Filing Search API](https://sec-api.io/docs/query-api). ```python from sec_api import PdfGeneratorApi pdfGeneratorApi = PdfGeneratorApi("YOUR_API_KEY") # Exhibit 99.1, the earnings press release attached to an 8-K url = "https://www.sec.gov/Archives/edgar/data/320193/000032019326000018/a8-kex991q3202606272026.htm" pdf = pdfGeneratorApi.get_pdf(url) with open("earnings-press-release.pdf", "wb") as f: f.write(pdf) ``` ## Convert the filings of a company The PDF Generator pairs with the [Filing Search API](https://sec-api.io/docs/query-api): search returns the URLs, the generator converts them. The example saves the last five Apple 8-K filings as PDFs. ```python from sec_api import QueryApi, PdfGeneratorApi queryApi = QueryApi("YOUR_API_KEY") pdfGeneratorApi = PdfGeneratorApi("YOUR_API_KEY") query = { "query": 'ticker:AAPL AND formType:"8-K"', "from": "0", "size": "5", "sort": [{"filedAt": {"order": "desc"}}], } filings = queryApi.get_filings(query)["filings"] for filing in filings: url = filing["linkToFilingDetails"] name = filing["accessionNo"] + ".pdf" with open(name, "wb") as f: f.write(pdfGeneratorApi.get_pdf(url)) print("saved", name) ``` ## Handling the 202 response A filing published moments ago may not be converted yet. The API then returns HTTP 202 rather than the PDF, meaning the conversion has been enqueued. Retry the same request after 5 seconds. Retrying 3 to 4 times usually returns the final PDF. See the [FAQ](https://sec-api.io/docs/sec-filings-to-pdf-generator-api#faq) for the retry ceiling and when to report a failure. ```python import time from sec_api import PdfGeneratorApi pdfGeneratorApi = PdfGeneratorApi("YOUR_API_KEY") def get_pdf_with_retry(url, attempts=4, delay=5): for attempt in range(attempts): pdf = pdfGeneratorApi.get_pdf(url) # a converted filing starts with the PDF magic number if pdf[:4] == b"%PDF": return pdf time.sleep(delay) raise RuntimeError("PDF not ready after " + str(attempts) + " attempts") pdf = get_pdf_with_retry( "https://www.sec.gov/Archives/edgar/data/320193/000032019323000106/aapl-20230930.htm" ) with open("apple-10-k.pdf", "wb") as f: f.write(pdf) ``` ## Good to know - The URL must point at the file itself under `sec.gov/Archives`. An inline XBRL viewer URL contains `/ix?doc=`, which has to be removed first. - Every image the filing references is rendered into the PDF, which is why proxy statements take longer to convert than press releases. - Forms 3, 4 and 5 are filed as XML. Passing the `xslF345X02` URL renders them through their stylesheet, so the PDF matches what a reader sees on the EDGAR viewer rather than showing raw XML. - Each filing is converted once and then stored, so the second request for the same URL returns the PDF immediately.