Is it possible to number the headings in a Google Docs/Drive document?
-
91How is it still not supported natively? – Janusz Skonieczny Oct 26 '17 at 11:55
-
9Imagine it being still not supported in 2022 – Francesco Cariaggi Jun 15 '22 at 07:10
7 Answers
If you want something more easy, there is a Google Add-On called "Table of Contents" that will allow you to number your headings.
To install this add-on:
- Click on the Add-Ons > Get Add-Ons.
- Click on the "Table of Contents" icon or search for this addon to install it
Then your Table of Contents should appear in your sidebar. Click on Heading Numbers Format menu, and choose 1.2.3
You have to reformat your document if you have an old one in order to 'refresh' the numbers, but actually the addon works very well.
I've seen the answer in this forum.
-
5In case the sidebar is not shown, go to _"Add-ons->Table of contents->Show in sidebar"_. – Steven Jeuris Apr 30 '18 at 09:02
-
3I think anyone can call their add-on "Table of Contents". So a link to the actual add-on is helpful. I'm guessing you mean this one: https://chrome.google.com/webstore/detail/table-of-contents/ickpeaanccmmabadbfiknbobkmkdnnaj – nealmcb Mar 18 '19 at 15:18
-
How is the plugin installed - per machine / browser, per document, per user on google docs? What happens if others want to edit the document? – Sybille Peters Feb 01 '20 at 09:18
-
Should we worry about the chance that the plugin can read the whole document? Or it wouldn't be able to? – Miao ZhiCheng Feb 24 '20 at 10:29
-
1Sadly, this plugin seems to be broken. It fails to install due to an authorisation issue. Are others getting the same result? – gavdotnet Mar 13 '20 at 23:27
-
@gavdotnet you're right, it seems that Google has disabled this plugin/extension atm.. :/ – Aitor Mar 19 '20 at 19:18
-
@gavdotnet yes, same issue here. I just send an email to contact@lumapps.com – Joachim Apr 15 '20 at 08:01
-
1
-
> Then your Table of Contents should appear in your sidebar. It doesn't. And there is no "Add-ons -> Table of Contents -> Show in sidebar" And getting to the "Settings -> Enable for this document" has no effect either. Weird that a feature that was in 1964 Runoff is not in Google Docs. – Michael Reiche Aug 05 '22 at 23:49
Update: now available in github.
Update 2: now handling empty headings and blank lines thanks to 2 pull requests on github.
Update 3: github and code below fixed to handle new Docs HEADING identification.
I modified the script mentioned by Mikko Ohtamaa and created a Google Apps Script that adds a Headings tools Document menu that allows you to:
- auto number Heading
- clear Headings numbers
How to auto number Google Documents Headings:
- Open your document > Tools > Script editor...
- Start a blank project
- Paste the the code below and save with your preffered name
- Select Run > onOpen and authorize the script for the first time
- Select Run > onOpen
- Change to your Document and try the functions on the Headings tools custom menu created.
~~Disclaimer: you may have issues with empty Headings.. But you can always fix them and run action again.~~
Code to copy and paste:
function onOpen() {
DocumentApp.getUi().createMenu('Headings Tools')
.addItem('Auto Number Headings', 'numberHeadingsAdd')
.addItem('Clear Heading Numbers', 'numberHeadingsClear')
.addToUi();
}
function numberHeadingsAdd(){
numberHeadings(true);
}
function numberHeadingsClear(){
numberHeadings(false);
}
function numberHeadings(add){
var document = DocumentApp.getActiveDocument();
var body = document.getBody();
var paragraphs = document.getParagraphs();
var numbers = [0,0,0,0,0,0,0];
for (var i in paragraphs) {
var element = paragraphs[i];
var text = element.getText()+'';
var type = element.getHeading()+'';
// exclude everything but headings
if (!type.match(/HEADING\d/)) {
continue;
}
// exclude empty headings (e.g. page breaks generate these)
if( text.match(/^\s*$/)){
continue;
}
if (add == true) {
var level = new RegExp(/HEADING(\d)/).exec(type)[1];
var numbering = '';
numbers[level]++;
for (var currentLevel = 1; currentLevel <= 6; currentLevel++) {
if (currentLevel <= level) {
numbering += numbers[currentLevel] + '.';
} else {
numbers[currentLevel] = 0;
}
}
Logger.log(text);
var newText = numbering + ' ' + text.replace(/^[0-9\.\s]+/, '');
element.setText(newText);
Logger.log([newText]);
} else {
Logger.log(text);
element.setText(text.replace(/^[0-9\.\s]+/, ''));
}
}
}

- 992
- 1
- 9
- 17
-
I am glad to know @IvanCachicatari I am planning on making an improved version to launch as an Add-on this way we don't need to open the script editor each time... – Luciano May 09 '14 at 14:08
-
-
2@IvanCachicatari Great idea, there you have it! https://github.com/lpanebr/autoNumberHeadings – Luciano May 13 '14 at 18:14
-
Great script! Is there a way to make the "Headings tools" menu permanent for all google documents? Currently the script has to be run every time a document is re-opened. – Andy Longwill Jul 11 '14 at 11:12
-
2@MrGravity the way to achieve that is to convert the script into a [Add-On for Google Drive](https://developers.google.com/apps-script/add-ons/) I plan in doing that but am out of time now.. – Luciano Jul 11 '14 at 14:21
-
Unfortunately, that reformatted my document a bit (removed inserted page breaks) and it numbered some empty lines as if they were headings. removing those lines and re-running the script resulted in same behavior. – Konstantin Jan 25 '17 at 07:19
-
@Konstantin numbered empty lines happen because you probably have a Heading Styles aplied to those empty lines. Make sure that empty line get the Paragraph Style and this should be fixed. – Luciano Jan 30 '17 at 11:12
-
1Wow! I feel like it's 90-ties again. Do we really need a script to accomplish such a basic thing like heading numbering? Now I understand why there are all this programming initiatives — our kids really need to know their JavaScript to write any work document ;P – Janusz Skonieczny Feb 13 '18 at 15:52
-
You made my day. But it again reminds me that online editors are still far from the functionality of desktop apps. – Marek Vitek Mar 15 '19 at 08:51
-
This doesn't work for me on new documents. I have on older one that it works on (https://docs.google.com/document/d/1aAC50vsCDVu45CiFuYSjx-lSHjyT7Tx2ef_qwRm_TvU/edit) and a newer one that it doesn't (https://docs.google.com/document/d/1J-K3T2VM34q3k3W7bl_UFzTNtawVMMmI8wSRcpt9Q1c/edit). I don't see any difference between the two. :| – Ginger McMurray Mar 02 '20 at 20:48
-
Changing the following has worked for me: Replace "Heading " (including the space after the 'g') to "HEADING" (without the space after the 'g'). i.e. capitalize the word and remove the space in the following two lines: line1: if (!type.match(/Heading \d/)) { line2: var level = new RegExp(/Heading (\d)/).exec(type)[1]; This might break something else but so far it works for me. – nsof Mar 03 '20 at 10:00
-
I'm sorry @GingerMcMurray. nsof is right and I've just merged a pull request in the github repo that applies that fix! – Luciano Mar 04 '20 at 11:43
-
1@Luciano that *kinda* works. I'm seeing a weird thing happening. If I cut and paste the code from git I get one of two results: nothing happens or a regex parse error at line 38. In order to get it to work I have to 1) cut and paste the git code from 10/16/17, 2) save, 3) manually make the changes nsof suggested, 4) save and run as listed above. I noticed a slight difference: line 38 in your version removes the parenthesis around \d. – Ginger McMurray Mar 04 '20 at 19:25
-
@GingerMcMurray thank you! That parenthesis was remove by mistake! I've already fixed it in the github repository. – Luciano Mar 05 '20 at 21:56
-
-
You can use the default `alt+/` and start typing "Auto". The `alt+/` shortcut lets you activate any item in the menus, even those created by scripts; – Luciano May 04 '20 at 20:14
Since writing (April 2020), a lot of proposed apps are obsolete or do not working anymore.
The method for numbered headings I've found working is the following:
- Go to Get add-ons
- Search and install Markdown Tools
Markdown Tools has an option to use numbered headings. Works like a charm with the built-in Table of Contents of Google.
To create a table of contents:
- Go to menu item Insert and select Table of Contents

- 351
- 3
- 5
-
1This is super useful! I wouldn't have thought that a simple TOC numbering functionality would be in a markdown tool, but it works great, thanks! – prrao May 31 '20 at 00:34
-
1At first I didn't like I had to select the menu item each time I wanted a heading number. But one can just type in the heading number, and only use the menu item if the non-consecutive heading numbers starts being irritating. I now appreciate the plumbing type of implementation. – Axel Bregnsbo Oct 06 '21 at 13:47
All you have to do is copy/paste previous headers.
If you copy and paste any item of numbered list, then it retains its numbering, and automatically changes the number in relevant cases.

- 3,880
- 1
- 27
- 21
-
2
-
1Indeed, this is the easiest, NATIVE solution (if you're still in the editing phase)! – Demis Sep 29 '19 at 22:13
-
1As far as I can tell, this requires that you indent with each heading level you descend into. Is that the case or is there another way? – gavdotnet Mar 13 '20 at 23:26
-
5The problem is: you need to copy headings from *the same document*. If you copy a "heading 1" for example from another html document, despite the "heading x" formatting retained it will not have the number. This means that if you already have another document with bunch of text that you want to copy-paste, your solution would require too much manual work. Or actually: it is the same if you already have a document and you just want to have headings there enumerated. – Hi-Angel May 07 '20 at 13:51
-
This is indeed the appropriate answer, I could not in good conscience install the Add-in since it requires the access rights to read any document you're using it in! – Oliver Gray Jul 07 '22 at 16:36
I wrote a version for doing markdown headings, but it also supports plain heading numbers as well. The source is here https://github.com/jordan2175/markdown-tools and is available via G Suite Marketplace as "Markdown Tools".

- 878
- 2
- 10
- 20
-
Hi @jordan2175 the add-on is great. It woluld be nice if the TOC it generates had page numbers. – David Lopez Jan 04 '20 at 19:12
The previously mentioned add-on "Table of contents" is not available as of today. I installed the one called "Markdown Tools" Once installed, you must apply native heading styles and then go to Add-Ons>Markdown Tools >Heading numbers and choose the desired numbering style which will be appplied to all headings in the doc.

- 353
- 4
- 13
-
Note, that this extension will use Markdown-based formatting, e.g. it'll change headings to look like `## 4.1 Foo`. The headings and ToC are also static and have to be manually regenerated. The ToC is also formatted in markdown style. On the plus side, the extension is open source and works client-side, so your docs are private. – crypdick Jan 19 '23 at 17:02
Firsly thanks to Luciano for this share.
I modified its code to also keep the number when the title starts with a number.
For example:
Title: 1000 euros, taxable threshold ?
Old script :
- euros, taxable threshold ?
New script
- 1000 euros, taxable threshold ?
Code:
function onOpen() {
DocumentApp.getUi().createMenu('Numérotation des titres')
.addItem('Ajouter / Mettre à jours Numérotation', 'numberHeadingsAdd')
.addItem('Supprimer Numérotation', 'numberHeadingsClear')
.addToUi();
}
function numberHeadingsAdd(){
numberHeadings(true);
}
function numberHeadingsClear(){
numberHeadings(false);
}
function numberHeadings(add){
var document = DocumentApp.getActiveDocument();
var body = document.getBody();
var paragraphs = document.getParagraphs();
var numbers = [0,0,0,0,0,0,0];
for (var i in paragraphs) {
var element = paragraphs[i];
var text = element.getText()+'';
var type = element.getHeading()+'';
// exclude everything but headings
if (!type.match(/HEADING\d/)) {
continue;
}
// exclude empty headings (e.g. page breaks generate these)
if( text.match(/^\s*$/)){
continue;
}
if (add == true) {
var level = new RegExp(/HEADING(\d)/).exec(type)[1];
var numbering = '';
numbers[level]++;
for (var currentLevel = 1; currentLevel <= 6; currentLevel++) {
if (currentLevel <= level) {
numbering += numbers[currentLevel] + '.';
} else {
numbers[currentLevel] = 0;
}
}
Logger.log(text);
var newText = numbering + ' ' + text.replace(/^[0-9\.\s]+[.]/, '');
element.setText(newText);
Logger.log([newText]);
} else {
Logger.log(text);
element.setText(text.replace(/^[0-9\.\s]+[.]/, ''));
}
}
}

- 1