> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Loading PDFs

> Demonstrates loading a PDF with PyPDFLoader, splitting into page documents, inspecting content and metadata, and preparing pages for embeddings and RAG pipelines.

In this lesson you'll learn how to load a PDF and split it into pages as the first step of a Retrieval-Augmented Generation (RAG) pipeline. We'll use a small, fictitious employee handbook for "Lakeside Bicycles" — a simple three-page PDF containing policies such as leave and discipline procedures. The goal is to extract the handbook text, split it into page-level documents, inspect the results, and prepare the output for downstream steps like embedding, indexing, and building a Q\&A/chat interface.

<Callout icon="lightbulb" color="#1CB2FE">
  Before running the examples, install the required packages. A typical install command is:

  ```bash theme={null}
  pip install langchain-community pypdf
  ```

  See [langchain-community on PyPI](https://pypi.org/project/langchain-community) and [pypdf on PyPI](https://pypi.org/project/pypdf) for details. For LangChain docs, visit [LangChain Documentation](https://langchain.readthedocs.io/en/latest/).
</Callout>

## Example dataset

From a notebook or shell, list the dataset directory:

```bash theme={null}
!ls data
```

```text theme={null}
handbook.pdf
```

## Load and split the PDF into page documents

We use the PyPDFLoader from the langchain-community package. The loader's `load_and_split()` method extracts text and returns a list of LangChain `Document` objects (one per page by default).

```python theme={null}
from langchain_community.document_loaders import PyPDFLoader

loader = PyPDFLoader("data/handbook.pdf")
pages = loader.load_and_split()
```

Check how many page documents were produced:

```python theme={null}
len(pages)
```

```text theme={null}
3
```

## What each page Document contains

Each item in `pages` is a LangChain `Document` with two primary attributes:

|      Attribute | Description                                         | Example                                      |
| -------------: | --------------------------------------------------- | -------------------------------------------- |
| `page_content` | Extracted text for that page                        | Short string containing page text            |
|     `metadata` | Metadata about the page (source, page number, etc.) | `{"source": "data/handbook.pdf", "page": 1}` |

## Inspect a page's content and metadata

View the first page's extracted text:

```python theme={null}
# First page content
pages[0].page_content
```

```text theme={null}
"complaint or concern about your work situation. You can contact the HR department for more information on the discipline and grievance procedures. We hope that this handbook has given you a clear and comprehensive overview of what it means to work at LakeSide Bicycles. If you have any questions or suggestions, please feel free to contact the HR department. We look forward to working with you and making LakeSide Bicycles a great place to work!"
```

View the first page's metadata:

```python theme={null}
# First page metadata
pages[0].metadata
```

```json theme={null}
{"source": "data/handbook.pdf", "page": 1}
```

## Iterate pages for inspection or processing

You can loop over `pages` to print metadata and a snippet of each page. This is useful for quick validation before moving to embeddings or indexing.

```python theme={null}
for i, p in enumerate(pages, start=1):
    print(f"Page {i} metadata: {p.metadata}")
    print(p.page_content[:200])  # print first 200 chars for a quick preview
    print("---")
```

## Next steps in a RAG pipeline

After successfully loading and splitting the PDF, common next steps are:

* Clean or normalize the text if necessary (remove headers/footers).
* Create embeddings for each page using an embeddings model.
* Store embeddings in a vector store (e.g., FAISS, Pinecone, Weaviate).
* Build a retriever and attach a language model for Q\&A/chat over the handbook.

References:

* LangChain docs: [https://langchain.readthedocs.io/en/latest/](https://langchain.readthedocs.io/en/latest/)
* Vector stores: FAISS, Pinecone, Weaviate

<Callout icon="warning" color="#FF6B6B">
  Scanned or image-based PDFs will not yield good text using PyPDFLoader alone — they need OCR (e.g., Tesseract, Amazon Textract, or other OCR services) before or during loading. Also, encrypted PDFs may require a decryption key or preprocessing.
</Callout>

## Tips and common issues

* If pages contain repeated header/footer text, consider removing those segments during preprocessing to improve retrieval relevance.
* Verify encoding and whitespace issues on extraction; sometimes lines may be broken incorrectly and require normalization.
* For large PDFs, consider splitting on semantic boundaries (sections or paragraphs) instead of fixed pages to get better retrieval granularity.

Now that the handbook is loaded and split into page-level Documents, you can proceed to embedding, indexing, and building your RAG-powered Q\&A or chat application. Similar loader patterns apply to web pages and other document formats (use appropriate loaders and OCR tools where necessary).

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/langchain/module/e47b44c9-65c3-46f8-8bed-b075a18ab12b/lesson/18155e0f-cc83-4438-ac30-051e60337344" />
</CardGroup>
