{"id":230,"date":"2026-10-03T09:21:47","date_gmt":"2026-10-03T17:21:47","guid":{"rendered":"https:\/\/www.tonybhimani.com\/programming-blog\/?p=230"},"modified":"2026-10-03T10:10:47","modified_gmt":"2026-10-03T18:10:47","slug":"creating-a-simple-web-based-signature-pad-with-html5-canvas","status":"publish","type":"post","link":"https:\/\/www.tonybhimani.com\/programming-blog\/creating-a-simple-web-based-signature-pad-with-html5-canvas\/","title":{"rendered":"Creating a Simple Web-Based Signature Pad with HTML5 Canvas"},"content":{"rendered":"<p>A friend recently asked me if creating a signature pad directly in a web page was difficult.<\/p>\n<p>His company needed something that would allow a user to sign a document or form electronically, and they were considering asking their existing consultant to build it.<\/p>\n<p>I told him it wasn&#8217;t particularly difficult.<\/p>\n<p>He asked how I would do it, then decided he didn&#8217;t want to know.<\/p>\n<p>So of course, I started thinking about how I would build it.<\/p>\n<p>The basic idea is actually pretty simple. Modern web browsers already give us most of what we need. We can use an HTML5 <code dir=\"ltr\">&lt;canvas&gt;<\/code> element as a drawing surface, JavaScript to capture the user&#8217;s mouse or touch movements, convert the canvas into an image, and then upload that image to a server.<\/p>\n<p>For this example, we&#8217;ll build the basic signature pad ourselves rather than using a third-party signature library.<\/p>\n<p>There are plenty of libraries available that can provide more advanced functionality, and those may be appropriate for a production application. The goal here is different.<\/p>\n<p>This is about understanding how it works.<\/p>\n<h2>The Basic Architecture<\/h2>\n<p>The process looks something like this:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-233 size-large\" src=\"https:\/\/www.tonybhimani.com\/programming-blog\/wp-content\/uploads\/2026\/10\/Html5CanvasSignaturePadDiagram_20261003083802136-1024x351.jpg\" alt=\"HTML5 Canvas Signature Pad Diagram\" width=\"1024\" height=\"351\" srcset=\"https:\/\/www.tonybhimani.com\/programming-blog\/wp-content\/uploads\/2026\/10\/Html5CanvasSignaturePadDiagram_20261003083802136-1024x351.jpg 1024w, https:\/\/www.tonybhimani.com\/programming-blog\/wp-content\/uploads\/2026\/10\/Html5CanvasSignaturePadDiagram_20261003083802136-300x103.jpg 300w, https:\/\/www.tonybhimani.com\/programming-blog\/wp-content\/uploads\/2026\/10\/Html5CanvasSignaturePadDiagram_20261003083802136-768x263.jpg 768w, https:\/\/www.tonybhimani.com\/programming-blog\/wp-content\/uploads\/2026\/10\/Html5CanvasSignaturePadDiagram_20261003083802136.jpg 1400w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<pre><strong>User draws \u2192 Canvas captures the drawing \u2192 \nCanvas becomes a PNG \u2192 PNG is uploaded \u2192 \nServer saves the image<\/strong><\/pre>\n<p>That&#8217;s really all there is to it.<\/p>\n<p>The browser handles the drawing, while the server handles storing the resulting image.<\/p>\n<p>For this example, I&#8217;ll show both a PHP backend and a Python Flask backend.<\/p>\n<h2>The Frontend<\/h2>\n<p>We&#8217;ll start with a simple HTML page containing a canvas and two buttons.<\/p>\n<p>One button clears the signature pad, and the other submits the signature.<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\n&lt;!DOCTYPE html&gt;\n&lt;html lang=&quot;en&quot;&gt;\n&lt;head&gt;\n    &lt;meta charset=&quot;UTF-8&quot;&gt;\n    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;\n    &lt;title&gt;Universal Signature Pad&lt;\/title&gt;\n\n    &lt;style&gt;\n        .pad-container {\n            width: 100%;\n            max-width: 450px;\n            margin: 20px auto;\n            text-align: center;\n            font-family: sans-serif;\n        }\n\n        canvas {\n            border: 2px dashed #ccc;\n            background: #fff;\n            cursor: crosshair;\n            touch-action: none;\n        }\n\n        .controls {\n            margin-top: 15px;\n        }\n\n        button {\n            padding: 12px 24px;\n            margin: 0 5px;\n            cursor: pointer;\n            font-size: 16px;\n            border-radius: 4px;\n            border: 1px solid #ccc;\n        }\n\n        #upload-btn {\n            background: #007BFF;\n            color: white;\n            border: none;\n        }\n    &lt;\/style&gt;\n&lt;\/head&gt;\n\n&lt;body&gt;\n\n&lt;div class=&quot;pad-container&quot;&gt;\n    &lt;h3&gt;Sign Your Name&lt;\/h3&gt;\n\n    &lt;canvas id=&quot;signature-pad&quot; width=&quot;400&quot; height=&quot;250&quot;&gt;&lt;\/canvas&gt;\n\n    &lt;div class=&quot;controls&quot;&gt;\n        &lt;button id=&quot;clear-btn&quot;&gt;Clear&lt;\/button&gt;\n        &lt;button id=&quot;upload-btn&quot;&gt;Submit&lt;\/button&gt;\n    &lt;\/div&gt;\n&lt;\/div&gt;\n\n&lt;script&gt;\n    const canvas = document.getElementById(&#039;signature-pad&#039;);\n    const ctx = canvas.getContext(&#039;2d&#039;);\n\n    const clearBtn = document.getElementById(&#039;clear-btn&#039;);\n    const uploadBtn = document.getElementById(&#039;upload-btn&#039;);\n\n    let isDrawing = false;\n\n    \/\/ Brush setup\n    ctx.strokeStyle = &#039;#111111&#039;;\n    ctx.lineWidth = 3;\n    ctx.lineCap = &#039;round&#039;;\n    ctx.lineJoin = &#039;round&#039;;\n\n    function getXY(e) {\n        const rect = canvas.getBoundingClientRect();\n\n        const clientX = e.touches\n            ? e.touches&#x5B;0].clientX\n            : e.clientX;\n\n        const clientY = e.touches\n            ? e.touches&#x5B;0].clientY\n            : e.clientY;\n\n        return {\n            x: clientX - rect.left,\n            y: clientY - rect.top\n        };\n    }\n\n    function startDrawing(e) {\n        isDrawing = true;\n\n        const coords = getXY(e);\n\n        ctx.beginPath();\n        ctx.moveTo(coords.x, coords.y);\n\n        if (e.touches) {\n            e.preventDefault();\n        }\n    }\n\n    function draw(e) {\n        if (!isDrawing) return;\n\n        const coords = getXY(e);\n\n        ctx.lineTo(coords.x, coords.y);\n        ctx.stroke();\n\n        if (e.touches) {\n            e.preventDefault();\n        }\n    }\n\n    function stopDrawing() {\n        isDrawing = false;\n    }\n\n    \/\/ Desktop mouse events\n    canvas.addEventListener(&#039;mousedown&#039;, startDrawing);\n    canvas.addEventListener(&#039;mousemove&#039;, draw);\n    window.addEventListener(&#039;mouseup&#039;, stopDrawing);\n\n    \/\/ Mobile touch events\n    canvas.addEventListener(\n        &#039;touchstart&#039;,\n        startDrawing,\n        { passive: false }\n    );\n\n    canvas.addEventListener(\n        &#039;touchmove&#039;,\n        draw,\n        { passive: false }\n    );\n\n    window.addEventListener(&#039;touchend&#039;, stopDrawing);\n\n    \/\/ Clear the signature\n    clearBtn.addEventListener(&#039;click&#039;, () =&gt; {\n        ctx.clearRect(\n            0,\n            0,\n            canvas.width,\n            canvas.height\n        );\n    });\n\n    \/\/ Upload the signature\n    uploadBtn.addEventListener(&#039;click&#039;, () =&gt; {\n\n        canvas.toBlob((blob) =&gt; {\n\n            if (!blob) {\n                alert(&quot;Canvas is empty.&quot;);\n                return;\n            }\n\n            const formData = new FormData();\n\n            formData.append(\n                &#039;signature&#039;,\n                blob,\n                &#039;sig_&#039; + Date.now() + &#039;.png&#039;\n            );\n\n            fetch(&#039;upload.php&#039;, {\n                method: &#039;POST&#039;,\n                body: formData\n            })\n            .then(res =&gt; res.json())\n            .then(data =&gt; {\n\n                if (data.success) {\n                    alert(\n                        &#039;Uploaded! Saved as: &#039; +\n                        data.file\n                    );\n                } else {\n                    alert(\n                        &#039;Upload failed: &#039; +\n                        data.error\n                    );\n                }\n\n            })\n            .catch(err =&gt; {\n                console.error(&#039;Upload Error:&#039;, err);\n            });\n\n        }, &#039;image\/png&#039;);\n    });\n&lt;\/script&gt;\n\n&lt;\/body&gt;\n&lt;\/html&gt;\n<\/pre>\n<h2>Creating the Drawing Surface<\/h2>\n<p>The important part of the HTML is the canvas:<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">&lt;canvas id=&quot;signature-pad&quot; width=&quot;400&quot; height=&quot;250&quot;&gt;&lt;\/canvas&gt;<\/pre>\n<p>The canvas gives us a rectangular area that JavaScript can draw into.<\/p>\n<p>The <code>width<\/code> and <code>height<\/code> attributes define the canvas&#8217;s internal drawing dimensions. CSS can then control how the canvas is displayed on the page.<\/p>\n<p>We obtain the canvas and its 2D drawing context with:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">const canvas = document.getElementById(&#039;signature-pad&#039;);\nconst ctx = canvas.getContext(&#039;2d&#039;);<\/pre>\n<p>The <code>ctx<\/code> object gives us the methods needed to draw on the canvas.<\/p>\n<h2>Drawing the Signature<\/h2>\n<p>The basic drawing process is straightforward.<\/p>\n<p>When the user presses the mouse button or touches the screen, we begin a path:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">ctx.beginPath();\nctx.moveTo(coords.x, coords.y);<\/pre>\n<p>As the pointer moves, we draw lines between the previous position and the new position:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">ctx.lineTo(coords.x, coords.y);\nctx.stroke();<\/pre>\n<p>By doing this repeatedly while the user moves their finger or mouse, we create what appears to be a continuous handwritten signature.<\/p>\n<p>The brush itself is configured with:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">ctx.strokeStyle = &#039;#111111&#039;;\nctx.lineWidth = 3;\nctx.lineCap = &#039;round&#039;;\nctx.lineJoin = &#039;round&#039;;<\/pre>\n<p>The rounded line ends and joins make the signature look considerably more natural than using square-ended lines.<\/p>\n<h2>Mouse and Touch Input<\/h2>\n<p>One of the interesting parts of this example is that it handles both desktop and mobile input.<\/p>\n<p>On a desktop, we listen for mouse events:<\/p>\n<pre>mousedown\nmousemove\nmouseup<\/pre>\n<p>On a mobile device, we listen for touch events:<\/p>\n<pre>touchstart\ntouchmove\ntouchend<\/pre>\n<p>The <code>touch-action: none<\/code> CSS property is also important:<\/p>\n<pre class=\"brush: css; title: ; notranslate\" title=\"\">canvas {\n    touch-action: none;\n}<\/pre>\n<p>Without it, a browser may interpret a finger movement on the canvas as a request to scroll the page instead of drawing a signature.<\/p>\n<p>The <code>getXY()<\/code> function converts the mouse or touch position into coordinates relative to the canvas itself.<\/p>\n<h2>Turning the Canvas Into an Image<\/h2>\n<p>Once the user clicks Submit, we need to turn the drawing into something that can be sent to a server.<\/p>\n<p>That&#8217;s where <code>toBlob()<\/code> comes in:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">canvas.toBlob((blob) =&gt; {\n    ...\n}, &#039;image\/png&#039;);<\/pre>\n<p>The browser creates a PNG image from the canvas and gives us a <code>Blob<\/code> containing the binary image data.<\/p>\n<p>We then place that blob into a <code>FormData<\/code> object:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">const formData = new FormData();\n\nformData.append(\n    &#039;signature&#039;,\n    blob,\n    &#039;sig_&#039; + Date.now() + &#039;.png&#039;\n);<\/pre>\n<p>The signature can now be sent to the server with a normal HTTP POST request:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">fetch(&#039;upload.php&#039;, {\n    method: &#039;POST&#039;,\n    body: formData\n});<\/pre>\n<p>If the site is running over HTTPS, the request is encrypted in transit.<\/p>\n<h2>PHP Backend<\/h2>\n<p>For a basic PHP implementation, the browser can send the image to an <code>upload.php<\/code> file.<\/p>\n<p>Here is the complete example:<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">&lt;?php\n\nheader(&#039;Content-Type: application\/json&#039;);\n\n$uploadDir = __DIR__ . &#039;\/signatures\/&#039;;\n\nif (!is_dir($uploadDir)) {\n    mkdir($uploadDir, 0755, true);\n}\n\nif ($_SERVER&#x5B;&#039;REQUEST_METHOD&#039;] === &#039;POST&#039; &amp;&amp;\n    isset($_FILES&#x5B;&#039;signature&#039;])) {\n\n    $file = $_FILES&#x5B;&#039;signature&#039;];\n\n    \/\/ Check the actual uploaded file type.\n    $fileType = mime_content_type($file&#x5B;&#039;tmp_name&#039;]);\n\n    if ($fileType !== &#039;image\/png&#039;) {\n        echo json_encode(&#x5B;\n            &#039;success&#039; =&gt; false,\n            &#039;error&#039; =&gt; &#039;Invalid image format.&#039;\n        ]);\n\n        exit;\n    }\n\n    \/\/ Generate our own filename.\n    $safeName =\n        &#039;sig_&#039; .\n        bin2hex(random_bytes(8)) .\n        &#039;.png&#039;;\n\n    $targetPath = $uploadDir . $safeName;\n\n    if (move_uploaded_file(\n        $file&#x5B;&#039;tmp_name&#039;],\n        $targetPath\n    )) {\n\n        echo json_encode(&#x5B;\n            &#039;success&#039; =&gt; true,\n            &#039;file&#039; =&gt; $safeName\n        ]);\n\n    } else {\n\n        echo json_encode(&#x5B;\n            &#039;success&#039; =&gt; false,\n            &#039;error&#039; =&gt; &#039;Failed to save file.&#039;\n        ]);\n    }\n\n} else {\n\n    echo json_encode(&#x5B;\n        &#039;success&#039; =&gt; false,\n        &#039;error&#039; =&gt; &#039;Invalid request data.&#039;\n    ]);\n}\n\n?&gt;\n<\/pre>\n<p>Notice that the PHP code doesn&#8217;t simply trust the filename supplied by the browser.<\/p>\n<p>It creates its own filename using <code>random_bytes()<\/code>.<\/p>\n<p>It also checks the uploaded file&#8217;s MIME type before saving it.<\/p>\n<p>For a real production application, additional validation should be added, including upload size limits, authentication and authorization, appropriate storage permissions, and stronger image validation.<\/p>\n<h2>Flask Backend<\/h2>\n<p>If Python is your preferred environment, the same basic idea can be implemented with Flask.<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">import os\nimport uuid\n\nfrom flask import Flask, request, jsonify\n\napp = Flask(__name__)\n\nUPLOAD_FOLDER = &#039;.\/signatures&#039;\nos.makedirs(UPLOAD_FOLDER, exist_ok=True)\n\n\n@app.route(&#039;\/upload-signature&#039;, methods=&#x5B;&#039;POST&#039;])\ndef upload_signature():\n\n    if &#039;signature&#039; not in request.files:\n        return jsonify({\n            &#039;success&#039;: False,\n            &#039;error&#039;: &#039;No file element received&#039;\n        }), 400\n\n    file = request.files&#x5B;&#039;signature&#039;]\n\n    if file.mimetype != &#039;image\/png&#039;:\n        return jsonify({\n            &#039;success&#039;: False,\n            &#039;error&#039;: &#039;Invalid file format&#039;\n        }), 400\n\n    filename = f&quot;sig_{uuid.uuid4().hex}.png&quot;\n\n    target_path = os.path.join(\n        UPLOAD_FOLDER,\n        filename\n    )\n\n    file.save(target_path)\n\n    return jsonify({\n        &#039;success&#039;: True,\n        &#039;file&#039;: filename\n    })\n\n\nif __name__ == &#039;__main__&#039;:\n    app.run(ssl_context=&#039;adhoc&#039;)\n<\/pre>\n<p>The frontend would need to change the <code>fetch()<\/code> URL from:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">fetch(&#039;upload.php&#039;, {<\/pre>\n<p>to something like:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">fetch(&#039;\/upload-signature&#039;, {<\/pre>\n<p>when using the Flask API.<\/p>\n<p>The <code>ssl_context='adhoc'<\/code> option is useful for local HTTPS testing. It creates a temporary development certificate.<\/p>\n<p>It is <strong>NOT<\/strong> intended to be your production Flask deployment.<\/p>\n<p>For a public application, Flask would normally run behind a production web server or reverse proxy that handles HTTPS.<\/p>\n<h2>A Note About Security<\/h2>\n<p>This example is intentionally simple.<\/p>\n<p>An uploaded signature is still an uploaded file, and uploads should never be treated as automatically trustworthy.<\/p>\n<p>A production application should consider things such as:<\/p>\n<ul>\n<li>File size limits.<\/li>\n<li>Authentication and authorization.<\/li>\n<li>Server-side image validation.<\/li>\n<li>Safe storage locations.<\/li>\n<li>Access controls.<\/li>\n<li>HTTPS.<\/li>\n<li>Rate limiting.<\/li>\n<li>Protection against users uploading files other than the intended image format.<\/li>\n<\/ul>\n<p>You should also think carefully about whether signatures should be publicly accessible by filename. Depending on what the signature is being used for, the uploaded image may contain sensitive information.<\/p>\n<h2>Why Build It Yourself?<\/h2>\n<p>There are plenty of JavaScript libraries that can create signature pads.<\/p>\n<p>For a real application, using an established library can make sense. Libraries can provide smoother strokes, pressure sensitivity, better touch handling, undo functionality, vector output, and other features.<\/p>\n<p>But sometimes the best way to understand a technology is to remove the abstraction.<\/p>\n<ul>\n<li>A signature pad isn&#8217;t magic.<\/li>\n<li>At its most basic level, we&#8217;re simply drawing on a canvas.<\/li>\n<li>The canvas gives us image data.<\/li>\n<li>JavaScript gives us a way to capture the user&#8217;s input.<\/li>\n<li><code>toBlob()<\/code> gives us an image we can send over HTTP.<\/li>\n<li>And the server saves it.<\/li>\n<\/ul>\n<p>Once you understand those pieces, you can build something much more sophisticated on top of them.<\/p>\n<h2>What&#8217;s Next?<\/h2>\n<p>This example deliberately keeps things simple.<\/p>\n<p>There are several things I would change or improve for a more modern implementation, including using Pointer Events instead of maintaining separate mouse and touch event handlers, handling high-DPI displays, improving the drawing algorithm, adding better server-side validation, and potentially storing signatures in a database or object storage system instead of directly on the web server.<\/p>\n<p>Those are topics for another article.<\/p>\n<p>For now, this is enough to demonstrate the basic idea:<\/p>\n<pre><strong>Draw it. Convert it. Upload it. Save it.<\/strong><\/pre>\n<p>And no, you don&#8217;t necessarily need to pay somebody a fortune just to put a box on a web page where someone can draw their name.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A friend recently asked me if creating a signature pad directly in a web page was difficult. His company needed something that would allow a user to sign a document or form electronically, and they were considering asking their existing consultant to build it. I told him it wasn&#8217;t particularly difficult. He asked how I [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":241,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8,7],"tags":[96,19,94,76,95],"class_list":["post-230","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripts","category-webdev","tag-html5-canvas","tag-javascript","tag-php","tag-python","tag-signature-pad"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.7 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Creating a Simple Web-Based Signature Pad with HTML5 Canvas - Tony&#039;s Programming Blog and Development Journal<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.tonybhimani.com\/programming-blog\/creating-a-simple-web-based-signature-pad-with-html5-canvas\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Creating a Simple Web-Based Signature Pad with HTML5 Canvas - Tony&#039;s Programming Blog and Development Journal\" \/>\n<meta property=\"og:description\" content=\"A friend recently asked me if creating a signature pad directly in a web page was difficult. His company needed something that would allow a user to sign a document or form electronically, and they were considering asking their existing consultant to build it. I told him it wasn&#8217;t particularly difficult. He asked how I [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.tonybhimani.com\/programming-blog\/creating-a-simple-web-based-signature-pad-with-html5-canvas\/\" \/>\n<meta property=\"og:site_name\" content=\"Tony&#039;s Programming Blog and Development Journal\" \/>\n<meta property=\"article:published_time\" content=\"2026-10-03T17:21:47+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-10-03T18:10:47+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.tonybhimani.com\/programming-blog\/wp-content\/uploads\/2026\/10\/Html5CanvasSignaturePadFeatured_20261003083909705.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1376\" \/>\n\t<meta property=\"og:image:height\" content=\"768\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Tony\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@TonyBhimani\" \/>\n<meta name=\"twitter:site\" content=\"@TonyBhimani\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Tony\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.tonybhimani.com\\\/programming-blog\\\/creating-a-simple-web-based-signature-pad-with-html5-canvas\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.tonybhimani.com\\\/programming-blog\\\/creating-a-simple-web-based-signature-pad-with-html5-canvas\\\/\"},\"author\":{\"name\":\"Tony\",\"@id\":\"https:\\\/\\\/www.tonybhimani.com\\\/programming-blog\\\/#\\\/schema\\\/person\\\/036db10e4bc2069453a60f580f91ab88\"},\"headline\":\"Creating a Simple Web-Based Signature Pad with HTML5 Canvas\",\"datePublished\":\"2026-10-03T17:21:47+00:00\",\"dateModified\":\"2026-10-03T18:10:47+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.tonybhimani.com\\\/programming-blog\\\/creating-a-simple-web-based-signature-pad-with-html5-canvas\\\/\"},\"wordCount\":1837,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.tonybhimani.com\\\/programming-blog\\\/#\\\/schema\\\/person\\\/036db10e4bc2069453a60f580f91ab88\"},\"image\":{\"@id\":\"https:\\\/\\\/www.tonybhimani.com\\\/programming-blog\\\/creating-a-simple-web-based-signature-pad-with-html5-canvas\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.tonybhimani.com\\\/programming-blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/Html5CanvasSignaturePadFeatured_20261003083909705.jpg\",\"keywords\":[\"html5 canvas\",\"javascript\",\"php\",\"python\",\"signature pad\"],\"articleSection\":[\"Scripts\",\"Web Dev\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.tonybhimani.com\\\/programming-blog\\\/creating-a-simple-web-based-signature-pad-with-html5-canvas\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.tonybhimani.com\\\/programming-blog\\\/creating-a-simple-web-based-signature-pad-with-html5-canvas\\\/\",\"url\":\"https:\\\/\\\/www.tonybhimani.com\\\/programming-blog\\\/creating-a-simple-web-based-signature-pad-with-html5-canvas\\\/\",\"name\":\"Creating a Simple Web-Based Signature Pad with HTML5 Canvas - Tony&#039;s Programming Blog and Development Journal\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.tonybhimani.com\\\/programming-blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.tonybhimani.com\\\/programming-blog\\\/creating-a-simple-web-based-signature-pad-with-html5-canvas\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.tonybhimani.com\\\/programming-blog\\\/creating-a-simple-web-based-signature-pad-with-html5-canvas\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.tonybhimani.com\\\/programming-blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/Html5CanvasSignaturePadFeatured_20261003083909705.jpg\",\"datePublished\":\"2026-10-03T17:21:47+00:00\",\"dateModified\":\"2026-10-03T18:10:47+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.tonybhimani.com\\\/programming-blog\\\/creating-a-simple-web-based-signature-pad-with-html5-canvas\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.tonybhimani.com\\\/programming-blog\\\/creating-a-simple-web-based-signature-pad-with-html5-canvas\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.tonybhimani.com\\\/programming-blog\\\/creating-a-simple-web-based-signature-pad-with-html5-canvas\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.tonybhimani.com\\\/programming-blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/Html5CanvasSignaturePadFeatured_20261003083909705.jpg\",\"contentUrl\":\"https:\\\/\\\/www.tonybhimani.com\\\/programming-blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/Html5CanvasSignaturePadFeatured_20261003083909705.jpg\",\"width\":1376,\"height\":768,\"caption\":\"HTML5 Canvas Signature Pad\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.tonybhimani.com\\\/programming-blog\\\/creating-a-simple-web-based-signature-pad-with-html5-canvas\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.tonybhimani.com\\\/programming-blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Creating a Simple Web-Based Signature Pad with HTML5 Canvas\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.tonybhimani.com\\\/programming-blog\\\/#website\",\"url\":\"https:\\\/\\\/www.tonybhimani.com\\\/programming-blog\\\/\",\"name\":\"Tony's Programming Blog and Development Journal\",\"description\":\"Sharing is caring... Especially with code\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.tonybhimani.com\\\/programming-blog\\\/#\\\/schema\\\/person\\\/036db10e4bc2069453a60f580f91ab88\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.tonybhimani.com\\\/programming-blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.tonybhimani.com\\\/programming-blog\\\/#\\\/schema\\\/person\\\/036db10e4bc2069453a60f580f91ab88\",\"name\":\"Tony\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/ed5a2a00dc5d9679e1fd2f29f60ca885a8e0f9d2c1aa2b5dabf05af02663b46c?s=96&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/ed5a2a00dc5d9679e1fd2f29f60ca885a8e0f9d2c1aa2b5dabf05af02663b46c?s=96&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/ed5a2a00dc5d9679e1fd2f29f60ca885a8e0f9d2c1aa2b5dabf05af02663b46c?s=96&r=g\",\"caption\":\"Tony\"},\"logo\":{\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/ed5a2a00dc5d9679e1fd2f29f60ca885a8e0f9d2c1aa2b5dabf05af02663b46c?s=96&r=g\"},\"sameAs\":[\"https:\\\/\\\/tonybhimani.com\\\/programming-blog\",\"https:\\\/\\\/x.com\\\/TonyBhimani\",\"https:\\\/\\\/www.youtube.com\\\/tonybhimani\"],\"url\":\"https:\\\/\\\/www.tonybhimani.com\\\/programming-blog\\\/author\\\/coding_magik\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Creating a Simple Web-Based Signature Pad with HTML5 Canvas - Tony&#039;s Programming Blog and Development Journal","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.tonybhimani.com\/programming-blog\/creating-a-simple-web-based-signature-pad-with-html5-canvas\/","og_locale":"en_US","og_type":"article","og_title":"Creating a Simple Web-Based Signature Pad with HTML5 Canvas - Tony&#039;s Programming Blog and Development Journal","og_description":"A friend recently asked me if creating a signature pad directly in a web page was difficult. His company needed something that would allow a user to sign a document or form electronically, and they were considering asking their existing consultant to build it. I told him it wasn&#8217;t particularly difficult. He asked how I [&hellip;]","og_url":"https:\/\/www.tonybhimani.com\/programming-blog\/creating-a-simple-web-based-signature-pad-with-html5-canvas\/","og_site_name":"Tony&#039;s Programming Blog and Development Journal","article_published_time":"2026-10-03T17:21:47+00:00","article_modified_time":"2026-10-03T18:10:47+00:00","og_image":[{"width":1376,"height":768,"url":"https:\/\/www.tonybhimani.com\/programming-blog\/wp-content\/uploads\/2026\/10\/Html5CanvasSignaturePadFeatured_20261003083909705.jpg","type":"image\/jpeg"}],"author":"Tony","twitter_card":"summary_large_image","twitter_creator":"@TonyBhimani","twitter_site":"@TonyBhimani","twitter_misc":{"Written by":"Tony","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.tonybhimani.com\/programming-blog\/creating-a-simple-web-based-signature-pad-with-html5-canvas\/#article","isPartOf":{"@id":"https:\/\/www.tonybhimani.com\/programming-blog\/creating-a-simple-web-based-signature-pad-with-html5-canvas\/"},"author":{"name":"Tony","@id":"https:\/\/www.tonybhimani.com\/programming-blog\/#\/schema\/person\/036db10e4bc2069453a60f580f91ab88"},"headline":"Creating a Simple Web-Based Signature Pad with HTML5 Canvas","datePublished":"2026-10-03T17:21:47+00:00","dateModified":"2026-10-03T18:10:47+00:00","mainEntityOfPage":{"@id":"https:\/\/www.tonybhimani.com\/programming-blog\/creating-a-simple-web-based-signature-pad-with-html5-canvas\/"},"wordCount":1837,"commentCount":0,"publisher":{"@id":"https:\/\/www.tonybhimani.com\/programming-blog\/#\/schema\/person\/036db10e4bc2069453a60f580f91ab88"},"image":{"@id":"https:\/\/www.tonybhimani.com\/programming-blog\/creating-a-simple-web-based-signature-pad-with-html5-canvas\/#primaryimage"},"thumbnailUrl":"https:\/\/www.tonybhimani.com\/programming-blog\/wp-content\/uploads\/2026\/10\/Html5CanvasSignaturePadFeatured_20261003083909705.jpg","keywords":["html5 canvas","javascript","php","python","signature pad"],"articleSection":["Scripts","Web Dev"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.tonybhimani.com\/programming-blog\/creating-a-simple-web-based-signature-pad-with-html5-canvas\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.tonybhimani.com\/programming-blog\/creating-a-simple-web-based-signature-pad-with-html5-canvas\/","url":"https:\/\/www.tonybhimani.com\/programming-blog\/creating-a-simple-web-based-signature-pad-with-html5-canvas\/","name":"Creating a Simple Web-Based Signature Pad with HTML5 Canvas - Tony&#039;s Programming Blog and Development Journal","isPartOf":{"@id":"https:\/\/www.tonybhimani.com\/programming-blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.tonybhimani.com\/programming-blog\/creating-a-simple-web-based-signature-pad-with-html5-canvas\/#primaryimage"},"image":{"@id":"https:\/\/www.tonybhimani.com\/programming-blog\/creating-a-simple-web-based-signature-pad-with-html5-canvas\/#primaryimage"},"thumbnailUrl":"https:\/\/www.tonybhimani.com\/programming-blog\/wp-content\/uploads\/2026\/10\/Html5CanvasSignaturePadFeatured_20261003083909705.jpg","datePublished":"2026-10-03T17:21:47+00:00","dateModified":"2026-10-03T18:10:47+00:00","breadcrumb":{"@id":"https:\/\/www.tonybhimani.com\/programming-blog\/creating-a-simple-web-based-signature-pad-with-html5-canvas\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.tonybhimani.com\/programming-blog\/creating-a-simple-web-based-signature-pad-with-html5-canvas\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.tonybhimani.com\/programming-blog\/creating-a-simple-web-based-signature-pad-with-html5-canvas\/#primaryimage","url":"https:\/\/www.tonybhimani.com\/programming-blog\/wp-content\/uploads\/2026\/10\/Html5CanvasSignaturePadFeatured_20261003083909705.jpg","contentUrl":"https:\/\/www.tonybhimani.com\/programming-blog\/wp-content\/uploads\/2026\/10\/Html5CanvasSignaturePadFeatured_20261003083909705.jpg","width":1376,"height":768,"caption":"HTML5 Canvas Signature Pad"},{"@type":"BreadcrumbList","@id":"https:\/\/www.tonybhimani.com\/programming-blog\/creating-a-simple-web-based-signature-pad-with-html5-canvas\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.tonybhimani.com\/programming-blog\/"},{"@type":"ListItem","position":2,"name":"Creating a Simple Web-Based Signature Pad with HTML5 Canvas"}]},{"@type":"WebSite","@id":"https:\/\/www.tonybhimani.com\/programming-blog\/#website","url":"https:\/\/www.tonybhimani.com\/programming-blog\/","name":"Tony's Programming Blog and Development Journal","description":"Sharing is caring... Especially with code","publisher":{"@id":"https:\/\/www.tonybhimani.com\/programming-blog\/#\/schema\/person\/036db10e4bc2069453a60f580f91ab88"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.tonybhimani.com\/programming-blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.tonybhimani.com\/programming-blog\/#\/schema\/person\/036db10e4bc2069453a60f580f91ab88","name":"Tony","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/ed5a2a00dc5d9679e1fd2f29f60ca885a8e0f9d2c1aa2b5dabf05af02663b46c?s=96&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/ed5a2a00dc5d9679e1fd2f29f60ca885a8e0f9d2c1aa2b5dabf05af02663b46c?s=96&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/ed5a2a00dc5d9679e1fd2f29f60ca885a8e0f9d2c1aa2b5dabf05af02663b46c?s=96&r=g","caption":"Tony"},"logo":{"@id":"https:\/\/secure.gravatar.com\/avatar\/ed5a2a00dc5d9679e1fd2f29f60ca885a8e0f9d2c1aa2b5dabf05af02663b46c?s=96&r=g"},"sameAs":["https:\/\/tonybhimani.com\/programming-blog","https:\/\/x.com\/TonyBhimani","https:\/\/www.youtube.com\/tonybhimani"],"url":"https:\/\/www.tonybhimani.com\/programming-blog\/author\/coding_magik\/"}]}},"_links":{"self":[{"href":"https:\/\/www.tonybhimani.com\/programming-blog\/wp-json\/wp\/v2\/posts\/230","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.tonybhimani.com\/programming-blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tonybhimani.com\/programming-blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tonybhimani.com\/programming-blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tonybhimani.com\/programming-blog\/wp-json\/wp\/v2\/comments?post=230"}],"version-history":[{"count":64,"href":"https:\/\/www.tonybhimani.com\/programming-blog\/wp-json\/wp\/v2\/posts\/230\/revisions"}],"predecessor-version":[{"id":300,"href":"https:\/\/www.tonybhimani.com\/programming-blog\/wp-json\/wp\/v2\/posts\/230\/revisions\/300"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.tonybhimani.com\/programming-blog\/wp-json\/wp\/v2\/media\/241"}],"wp:attachment":[{"href":"https:\/\/www.tonybhimani.com\/programming-blog\/wp-json\/wp\/v2\/media?parent=230"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tonybhimani.com\/programming-blog\/wp-json\/wp\/v2\/categories?post=230"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tonybhimani.com\/programming-blog\/wp-json\/wp\/v2\/tags?post=230"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}