<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: VolodymyrPTK</title>
    <description>The latest articles on DEV Community by VolodymyrPTK (@volodymyrptk).</description>
    <link>https://dev.to/volodymyrptk</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F789117%2F683e2999-4643-4513-9de3-dd2881f10a68.jpeg</url>
      <title>DEV Community: VolodymyrPTK</title>
      <link>https://dev.to/volodymyrptk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/volodymyrptk"/>
    <language>en</language>
    <item>
      <title>Extending n8n running locally python scripts using Flask</title>
      <dc:creator>VolodymyrPTK</dc:creator>
      <pubDate>Fri, 04 Jul 2025 10:35:41 +0000</pubDate>
      <link>https://dev.to/volodymyrptk/extending-n8n-running-locally-python-scripts-using-flask-1e7</link>
      <guid>https://dev.to/volodymyrptk/extending-n8n-running-locally-python-scripts-using-flask-1e7</guid>
      <description>&lt;p&gt;Hi everyone!&lt;/p&gt;

&lt;p&gt;I want to share what I've done to extend the functionality of n8n by running Python code using a Flask server, so don't need to pay for Cloudconver and similar APIs. I’m running n8n locally in Docker and have added a new image conversion function that converts images from PNG to Webp format. This is done through a Python script that I’ve integrated into my setup. I’ve also created an n8n node that calls this function, converts the image, and returns the converted image back to my workflow.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm0sm70bif4q6mqqxzva5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm0sm70bif4q6mqqxzva5.png" alt="Image description" width="800" height="431"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fujfmy9i6tv951a7rtibl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fujfmy9i6tv951a7rtibl.png" alt="Image description" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This ins json for import n8n node, just copy and paste inside n8n workflow&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "name": "Tests",
  "nodes": [
    {
      "parameters": {
        "method": "POST",
        "url": "http://host.docker.internal:5000/convert",
        "sendBody": true,
        "contentType": "multipart-form-data",
        "bodyParameters": {
          "parameters": [
            {
              "parameterType": "formBinaryData",
              "name": "file",
              "inputDataFieldName": "data"
            },
            {
              "name": "original_filename",
              "value": "={{ $binary.data.fileName || 'image.png' }}"
            }
          ]
        },
        "options": {}
      },
      "name": "Flask Converter",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.1,
      "position": [
        -820,
        20
      ],
      "id": "483881d3-6574-4eec-91e9-4715e185657c",
      "alwaysOutputData": false,
      "notes": "After importing, you must manually set this node to send the file using the instructions provided."
    }
  ],
  "pinData": {},
  "connections": {},
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "6ace63f3-e1f3-48ad-a929-c0ca4ba0887c",
  "meta": {
    "instanceId": "44c216c02c6f01f2fef8eb2ad71aa75c1545e5519733c0a1e6fb1f2fc1b2fa36"
  },
  "id": "mKN69KiJtr7j68C3",
  "tags": []
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;this is python script&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import sys
import os
from PIL import Image
from flask import Flask, request, send_file, jsonify
import io


def convert_png_to_webp(input_path, output_path=None, quality=80):
    if not input_path.lower().endswith('.png'):
        raise ValueError('Input file must be a PNG image suka.')

    if output_path is None:
        output_path = os.path.splitext(input_path)[0] + '.webp'

    with Image.open(input_path) as img:
        img.save(output_path, 'WEBP', quality=quality)
    print(f"Converted '{input_path}' to '{output_path}' (quality={quality})")


def main():
    if len(sys.argv) &amp;lt; 2:
        print("Usage: python png_to_webp_converter.py &amp;lt;input_png&amp;gt; [output_webp] [quality]")
        sys.exit(1)

    input_path = sys.argv[1]
    output_path = sys.argv[2] if len(sys.argv) &amp;gt; 2 else None
    quality = int(sys.argv[3]) if len(sys.argv) &amp;gt; 3 else 80

    try:
        convert_png_to_webp(input_path, output_path, quality)
    except Exception as e:
        print(f"Error: {e}")
        sys.exit(1)


app = Flask(__name__)

@app.route('/convert', methods=['POST'])
def convert():
    if 'file' not in request.files:
        return jsonify({'error': 'No file part'}), 400

    file = request.files['file']
    if not file or not getattr(file, 'filename', None):
        return jsonify({'error': 'No selected file'}), 400

    original_filename = request.form.get('original_filename', 'image.png')

    base_name = os.path.splitext(original_filename)[0]
    webp_filename = f"{base_name}.webp"

    try:
        img = Image.open(file.stream)

        if img.format != 'PNG':
            return jsonify({'error': f'Only PNG files are supported. Received: {img.format}'}), 400

        file.stream.seek(0)

        output = io.BytesIO()
        img.save(output, format='WEBP', quality=80)
        output.seek(0)

        return send_file(output, mimetype='image/webp', as_attachment=True, download_name=webp_filename)

    except Exception as e:
        return jsonify({'error': f'Error processing image: {str(e)}'}), 500

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=True)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
  </channel>
</rss>
