diff --git a/client/html/post_edit_sidebar.tpl b/client/html/post_edit_sidebar.tpl
index 4283c25..0fb878b 100644
--- a/client/html/post_edit_sidebar.tpl
+++ b/client/html/post_edit_sidebar.tpl
@@ -66,6 +66,12 @@
                 <a href class='add'>Add a note</a>
                 <%= ctx.makeTextarea({disabled: true, text: 'Content (supports Markdown)', rows: '8'}) %>
                 <a href class='delete inactive'>Delete selected note</a>
+                <% if (ctx.hasClipboard) { %>
+                    <br/>
+                    <a href class='copy'>Export notes to clipboard</a>
+                    <br/>
+                    <a href class='paste'>Import notes from clipboard</a>
+                <% } %>
             </section>
         <% } %>
 
diff --git a/client/js/controls/post_edit_sidebar_control.js b/client/js/controls/post_edit_sidebar_control.js
index 3c3f59d..72cabc9 100644
--- a/client/js/controls/post_edit_sidebar_control.js
+++ b/client/js/controls/post_edit_sidebar_control.js
@@ -5,6 +5,8 @@ const config = require('../config.js');
 const events = require('../events.js');
 const misc = require('../util/misc.js');
 const views = require('../util/views.js');
+const Note = require('../models/note.js');
+const Point = require('../models/point.js');
 const TagInputControl = require('./tag_input_control.js');
 const ExpanderControl = require('../controls/expander_control.js');
 const FileDropperControl = require('../controls/file_dropper_control.js');
@@ -25,6 +27,7 @@ class PostEditSidebarControl extends events.EventTarget {
         views.replaceContent(this._hostNode, template({
             post: this._post,
             enableSafety: config.enableSafety,
+            hasClipboard: document.queryCommandSupported('copy'),
             canEditPostSafety: api.hasPrivilege('posts:edit:safety'),
             canEditPostSource: api.hasPrivilege('posts:edit:source'),
             canEditPostTags: api.hasPrivilege('posts:edit:tags'),
@@ -107,6 +110,16 @@ class PostEditSidebarControl extends events.EventTarget {
                 'click', e => this._evtAddNoteClick(e));
         }
 
+        if (this._copyNotesLinkNode) {
+            this._copyNotesLinkNode.addEventListener(
+                'click', e => this._evtCopyNotesClick(e));
+        }
+
+        if (this._pasteNotesLinkNode) {
+            this._pasteNotesLinkNode.addEventListener(
+                'click', e => this._evtPasteNotesClick(e));
+        }
+
         if (this._deleteNoteLinkNode) {
             this._deleteNoteLinkNode.addEventListener(
                 'click', e => this._evtDeleteNoteClick(e));
@@ -252,6 +265,50 @@ class PostEditSidebarControl extends events.EventTarget {
         this._postNotesOverlayControl.switchToDrawing();
     }
 
+    _evtCopyNotesClick(e) {
+        e.preventDefault();
+        let textarea = document.createElement('textarea');
+        textarea.style.position = 'fixed';
+        textarea.style.opacity = '0';
+        textarea.value = JSON.stringify([...this._post.notes].map(note => ({
+            polygon: [...note.polygon].map(
+                point => [point.x, point.y]),
+            text: note.text,
+        })));
+        document.body.appendChild(textarea);
+        textarea.select();
+
+        let success = false;
+        try {
+            success = document.execCommand('copy');
+        } catch (err) {
+        }
+        textarea.blur();
+        document.body.removeChild(textarea);
+        alert(success
+            ? 'Notes copied to clipboard.'
+            : 'Failed to copy the text to clipboard. Sorry.');
+    }
+
+    _evtPasteNotesClick(e) {
+        e.preventDefault();
+        const text = window.prompt(
+            'Please enter the exported notes snapshot:');
+        if (!text) {
+            return;
+        }
+        const notesObj = JSON.parse(text);
+        this._post.notes.clear();
+        for (let noteObj of notesObj) {
+            let note = new Note();
+            for (let pointObj of noteObj.polygon) {
+                note.polygon.add(new Point(pointObj[0], pointObj[1]));
+            }
+            note.text = noteObj.text;
+            this._post.notes.add(note);
+        }
+    }
+
     _evtDeleteNoteClick(e) {
         e.preventDefault();
         if (e.target.classList.contains('inactive')) {
@@ -350,6 +407,14 @@ class PostEditSidebarControl extends events.EventTarget {
         return this._formNode.querySelector('.notes .add');
     }
 
+    get _copyNotesLinkNode() {
+        return this._formNode.querySelector('.notes .copy');
+    }
+
+    get _pasteNotesLinkNode() {
+        return this._formNode.querySelector('.notes .paste');
+    }
+
     get _deleteNoteLinkNode() {
         return this._formNode.querySelector('.notes .delete');
     }