Question: UPDATE: See second code block for the solution The question may seem simple but I haven't been able to find anything related to it:  How to start the page numbering index at a given page?  For example, let's consider a document composed of a front page, a table of content and then the document's content itself. How can I start the page numbering at the first section of this document instead of starting it at the first page? Note that I am not trying not to display the page number (which is trivial) but change which page is considered as the first page. Below is an example: import os from reportlab.lib.pagesizes import A4 from reportlab.platypus import BaseDocTemplate, PageTemplate, Frame, Paragraph, PageBreak, NextPageTemplate from reportlab.platypus.tableofcontents import TableOfContents from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle from reportlab.lib.units import inch # Importing inch unit class Example(BaseDocTemplate): def __init__(self, fname, **kwargs): super().__init__(fname, **kwargs) frame_example = Frame(self.leftMargin - 0.5*inch, self.bottomMargin + 0.25*inch, self.width + 1*inch, self.height - 0.5*inch, id='example') # Define some page templates to display the page number self.addPageTemplates([PageTemplate(id='front_page', frames=frame_example, onPage=self.doFootingsFrontPage), PageTemplate(id='other_pages', frames=frame_example, onPage=self.doFootings)]) self.elements = [] # Defining some basic paragrah styles for the example ps1 = ParagraphStyle(fontName='Helvetica', fontSize=14, name='frontPage_PS', leftIndent=20, firstLineIndent=-20, spaceBefore=5, leading=16) ps2 = ParagraphStyle(fontName='Helvetica', fontSize=12, name='header_PS', leftIndent=20, firstLineIndent=-20, spaceBefore=5, leading=16) ps3 = ParagraphStyle(fontName='Helvetica', fontSize=10, name='text_PS', leftIndent=20, firstLineIndent=-20, spaceBefore=5, leading=16) # Storing the styles into a class attribute so that we can call them later on self.styleSheet = getSampleStyleSheet() for style in [ps1, ps2, ps3]: self.styleSheet.add(style) # Generate the front page self.doFrontPage() # Initialize the TOC toc = TableOfContents(dotsMinLevel=0) toc.levelStyles = [self.styleSheet['header_PS']] # Add the TOC self.elements.append(toc) self.elements.append(PageBreak()) for n in range(2): self.doOtherPage(n) # Build the document self.multiBuild(self.elements) def afterFlowable(self, flowable): "Registers TOC entries." if flowable.__class__.__name__ == 'Paragraph': text = flowable.getPlainText() style = flowable.style.name if style == 'header_PS': self.notify('TOCEntry', (0, text, self.page)) def doFootings(self, canvas, doc): # Create the footer x = A4[0]-128 y = 40 canvas.saveState() txtFooting = "Page {}".format(int(canvas._pageNumber)) canvas.drawString(x, y, txtFooting) canvas.restoreState() def doFootingsFrontPage(self, canvas, doc): # Create the footer x = 50 y = 40 canvas.saveState() txtFooting = "I am the front page - I dont want to have a page number" canvas.drawString(x, y, txtFooting) canvas.restoreState() def doFrontPage(self): txt = 'This is the front page' self.elements.append(Paragraph(txt, self.styleSheet['frontPage_PS'])) self.elements.append(NextPageTemplate("other_pages")) self.elements.append(PageBreak()) def doOtherPage(self, n): txt = 'Header {:.0f}'.format(n+1) self.elements.append(Paragraph(txt, self.styleSheet['header_PS'])) txt ='Who stole my page number? I should be Page {:.0f}'.format(n+1) for ii in range(10): self.elements.append(Paragraph(txt, self.styleSheet['text_PS'])) self.elements.append(PageBreak()) if __name__ == '__main__': fname = os.path.abspath(os.path.join('.', 'example_reportlab.pdf')) Report = Example(fname)  In this example a PDF with 4 pages is generated, the front page, the table of content and two filling sections for the example. What I would like to obtain is to have the page numbering starting at the first section of the document (which is currently the page 3) and have it reflected into the Table of Content (i.e., Header 1 would be at page 1, Header 2 page 2 ...). Or even better, be able to index the first pages i, ii, iii ... then switch to a new numbering scheme 1, 2, 3 ... when a certain part of the document is reached. To my understanding it should be possible to do it; I found this example which states:  In real world documents there is another complication. You might have a fancy cover or front matter, and the logical page number 1 used in printing might not actually be page 1. Likewise, you might be doing a batch of customer docs in one RML job. So, in this case we have a more involved expression, and use the evalString tag to work out the number we want. In this example we did this by creating a name for the first page after the cover, <namedString id="page1"> <evalString default="XXX"> <pageNumber/>-+1 </evalString> </namedString>... This says 'work out the page number of the cover, add 1 and store that in the variable "page1" for future use'  But I haven't been able to make anything out of it. I also had a look at the tests implemented by the library (test_platypus_toc.py for an example) but haven't found anything relevant to my question. I am using Python 3.12.9, and reportlab 3.6.13. Before it is asked, no this answer is not what I am looking for (unless I tried it wrongly).  Below is the solution I came up with following Salt answer: import os from reportlab.lib import colors from reportlab.lib.pagesizes import A4 from reportlab.platypus import BaseDocTemplate, PageTemplate, Frame, Paragraph, PageBreak, NextPageTemplate from reportlab.platypus.tables import TableStyle from reportlab.platypus.tableofcontents import TableOfContents from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle from reportlab.lib.units import inch # Importing inch unit class Example(BaseDocTemplate): def __init__(self, fname, **kwargs): super().__init__(fname, **kwargs) self.start_page_number = None frame_example = Frame(self.leftMargin - 0.5*inch, self.bottomMargin + 0.25*inch, self.width + 1*inch, self.height - 0.5*inch, id='example') self.addPageTemplates([PageTemplate(id='front_page', frames=frame_example, onPage=self.doFootingsFrontPage), PageTemplate(id='other_pages', frames=frame_example, onPage=self.doFootings)]) self.elements = [] # Defining some basic paragrah style for the example ps1 = ParagraphStyle(fontName='Helvetica', fontSize=14, name='frontPage_PS', leftIndent=20, firstLineIndent=-20, spaceBefore=5, leading=16) ps2 = ParagraphStyle(fontName='Helvetica', fontSize=12, name='header_PS', leftIndent=20, firstLineIndent=-20, spaceBefore=5, leading=16) ps3 = ParagraphStyle(fontName='Helvetica', fontSize=10, name='text_PS', leftIndent=20, firstLineIndent=-20, spaceBefore=5, leading=16) # Storing the styles into a class attribute so that we can call them later on self.styleSheet = getSampleStyleSheet() for style in [ps1, ps2, ps3]: self.styleSheet.add(style) defaultTableStyle = TableStyle([ ('VALIGN', (0,0), (-1,-1), 'TOP'), ('RIGHTPADDING', (0,0), (-1,-1), 0), ('LEFTPADDING', (0,0), (-1,-1), 10), ('LINEBEFORE', (0,0), (0, -1), 2.5, colors.blue) ]) # Generate each page one by one self.doFrontPage() # Initialize the TOC toc = TableOfContents(dotsMinLevel=0) toc.levelStyles = [self.styleSheet['header_PS']] toc.tableStyle = defaultTableStyle # Add the TOC self.elements.append(toc) self.elements.append(PageBreak()) for n in range(2): self.doOtherPage(n) # Build the document self.multiBuild(self.elements) def afterFlowable(self, flowable): "Registers TOC entries." if flowable.__class__.__name__ == 'Paragraph': text = flowable.getPlainText() style = flowable.style.name if style == 'header_PS': if self.start_page_number is None: self.start_page_number = self.page page_number = self.page - self.start_page_number + 1 self.notify('TOCEntry', (0, text, page_number)) def doFootings(self, canvas, doc): # Create the footer x = A4[0]-128 y = 40 if self.start_page_number is not None: page_number = self.page - self.start_page_number + 1 if page_number < 1: return canvas.saveState() txtFooting = "Page {}".format(int(page_number)) canvas.drawString(x, y, txtFooting) canvas.restoreState() def doFootingsFrontPage(self, canvas, doc): # Create the footer x = 50 y = 40 canvas.saveState() txtFooting = "I am the front page - I dont want to have a page number" canvas.drawString(x, y, txtFooting) canvas.restoreState() def doFrontPage(self): txt = 'This is the front page' self.elements.append(Paragraph(txt, self.styleSheet['frontPage_PS'])) self.elements.append(NextPageTemplate("other_pages")) self.elements.append(PageBreak()) def doOtherPage(self, n): txt = 'Header {:.0f}'.format(n+1) self.elements.append(Paragraph(txt, self.styleSheet['header_PS'])) txt ='Who stole my page number? I should be Page {:.0f}'.format(n+1) for ii in range(10): self.elements.append(Paragraph(txt, self.styleSheet['text_PS'])) self.elements.append(PageBreak()) if __name__ == '__main__': fname = os.path.abspath(os.path.join('.', 'example_reportlab.pdf')) Report = Example(fname)  I followed Salt steps with the main difference being that I estimate the displayed page number instead of incrementing it. The displayed page number is then considered as nothing more than Reporlab's logical_page_number shifted by a fixed offset (self.start_page_number in my updated code). The +1 in page_number = self.page - self.start_page_number + 1 is only here to avoid indexing starting from 0.

Answer: ReportLab always uses physical page numbers, so to start numbering from a specific page (e.g., after the TOC), you need to manage it manually. Track your own logical_page_number, set a flag when the real content starts, and from that point on:  Increment your counter on each page.  Use it in the footer instead of canvas.getPageNumber().  Use it in TOC entries via notify().   This way, the visible numbering and TOC both start from 1 at the point you choose.