Of course! The term "Python word bookmark" can mean a few different things. I'll cover the most common interpretations with clear code examples.

Interpretation 1: Creating a "Bookmark" in a Word Document (Bookmark as a Named Location)
This is the most common use case. In Microsoft Word, a "bookmark" is a named location in a document that you can use for navigation or to reference a specific part of the text. With python-docx, you can create these bookmarks and add content to them.
What You'll Need
First, install the necessary library:
pip install python-docx
Code Example: Creating a Document with Bookmarks
This script will create a new Word document named bookmarked_document.docx. It will add some text, insert a "bookmark" named important_section, add more text, and then insert a hyperlink that jumps directly to that bookmark.
import docx
from docx.shared import Pt, RGBColor
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
# Create a new Document object
doc = docx.Document()
# --- Add a title ---= doc.add_paragraph('My Document with Bookmarks', style='Heading 1')alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
# --- Add some introductory text ---
doc.add_paragraph('This is the beginning of the document. You can read this part first.')
# --- 1. Add a Bookmark ---
# To add a bookmark, we add a run of text and give it a bookmark name.
# The bookmark itself is invisible in the final document, but it marks the location.
bookmark_para = doc.add_paragraph()
run = bookmark_para.add_run('This is the IMPORTANT SECTION. It is marked by a bookmark.')
run.font.bold = True
run.font.color.rgb = RGBColor(255, 0, 0) # Make it red
# The actual bookmark creation happens here.
# We add a XML element to the paragraph's XML.
bookmark_start = bookmark_para._element.xpath('.//w:bookmarkStart')
if not bookmark_start:
# If the bookmark doesn't exist, add it.
# This is a low-level operation. The tag is 'w:bookmarkStart'.
# The 'name' attribute is the bookmark's name.
doc.element.body.add_namespace('w', 'http://schemas.openxmlformats.org/wordprocessingml/2006/main')
bookmark_start_tag = doc.element.body.xpath('.//w:p[last()]')[0]
bookmark_start_tag.append(doc.element.nsdecls['w'] + '<w:bookmarkStart w:id="0" w:name="important_section"/><w:bookmarkEnd w:id="0"/>')
# --- Add more text after the bookmark ---
doc.add_paragraph('This comes after the important section.')
# --- 2. Add a Hyperlink to the Bookmark ---
# This is where the bookmark becomes useful. We can link directly to it.
# The '#' before the name signifies it's an internal bookmark link.
link_para = doc.add_paragraph('Click ')
run = link_para.add_run('here')
run.font.underline = True
run.font.color.rgb = RGBColor(0, 0, 255) # Make it blue
# Add the hyperlink. The '#' is crucial for internal bookmarks.
# Note: python-docx requires a URL, even for internal links. '#' works.
doc.add_hyperlink(run, anchor='#important_section', is_external=False)
link_para.add_run(' to jump to the important section.')
# --- Save the document ---
doc.save('bookmarked_document.docx')
print("Document 'bookmarked_document.docx' created successfully!")
How to Use the Output:

- Run the script.
- Open
bookmarked_document.docxin Microsoft Word. - You will see red, bold text.
- If you hold
Ctrland click the blue, underlined "here" text, your cursor will jump directly to the red, bold text. This is the power of bookmarks.
Interpretation 2: Bookmarking the Last Position in a Document (Like a "Resume Reading" Feature)
This is a common request for applications that process large documents. The goal is to save the last processed position (e.g., page number, paragraph index) so the script can resume from there later.
Concept
Since Word files don't have a built-in "last read position" field, you have to simulate it. The best way is to use Custom XML Properties. These are hidden data fields stored within the document that are perfect for this kind of metadata.
Code Example: Saving and Resuming a Position
This script will:
- Open an existing document.
- Read its current "bookmark" (the last processed paragraph).
- Continue processing from that point.
- Save the new position.
import docx
import os
# The document we will be working on
DOC_FILENAME = 'my_large_document.docx'
BOOKMARK_KEY = 'last_processed_paragraph'
def get_last_position(doc):
"""Retrieves the custom property value for our bookmark."""
try:
# Custom properties are stored in the core properties
return doc.core_properties.custom_properties[BOOKMARK_KEY]
except (KeyError, AttributeError):
# If the property doesn't exist, we start from the beginning (0)
return 0
def set_last_position(doc, position):
"""Sets the custom property value for our bookmark."""
if doc.core_properties.custom_properties is None:
# Initialize custom properties if they don't exist
doc.core_properties.custom_properties = docx.opc.coreprops.CustomProperties()
doc.core_properties.custom_properties[BOOKMARK_KEY] = position
def process_document():
"""Main function to process the document with resume capability."""
# --- Setup: Create a dummy document for this example ---
if not os.path.exists(DOC_FILENAME):
print(f"'{DOC_FILENAME}' not found. Creating a dummy one...")
dummy_doc = docx.Document()
for i in range(100):
dummy_doc.add_paragraph(f"This is paragraph number {i+1}. This is some sample text to make the document longer.")
dummy_doc.save(DOC_FILENAME)
# --- End of setup ---
# Open the document
doc = docx.Document(DOC_FILENAME)
all_paragraphs = doc.paragraphs
# 1. Get the last saved position
start_index = get_last_position(doc)
print(f"Resuming processing from paragraph index: {start_index}")
# 2. Process paragraphs from the saved position
for i in range(start_index, len(all_paragraphs)):
para = all_paragraphs[i]
# --- YOUR PROCESSING LOGIC GOES HERE ---
# For example, let's just make every 5th paragraph bold and blue
if (i + 1) % 5 == 0:
for run in para.runs:
run.font.bold = True
run.font.color.rgb = (0, 0, 255) # RGB for blue
# --------------------------------------
# 3. Update the bookmark periodically
# We update it every 10 paragraphs to avoid saving the file too often.
if i % 10 == 0:
set_last_position(doc, i + 1) # Save the index of the NEXT paragraph to process
doc.save(DOC_FILENAME)
print(f"Processed up to paragraph {i+1}. Bookmark saved.")
# 4. Final save and cleanup
set_last_position(doc, len(all_paragraphs)) # Mark the document as fully processed
doc.save(DOC_FILENAME)
print(f"Processing complete. Final bookmark set to {len(all_paragraphs)}.")
# Run the function
if __name__ == '__main__':
process_document()
How to Use This:

- Run the script once. It will create
my_large_document.docxand process the first 10 paragraphs, saving a "bookmark" at paragraph 11. - Run the script again. It will see the bookmark, skip the first 10 paragraphs, and continue processing from paragraph 11.
- Each time you run it, it will pick up where it left off.
Summary
| Use Case | Method | Key Library | Complexity |
|---|---|---|---|
| Named Location for Navigation | Insert XML <w:bookmarkStart> tags |
python-docx |
Medium |
| Resume Position/State | Use Custom XML Properties (core_properties) |
python-docx |
Low |
For most users asking about "Python word bookmark," Interpretation 1 is what they're looking for. Interpretation 2 is a more advanced but extremely useful pattern for automating document workflows.
