Import font in code node

Describe the problem/error/question

Hi everyone, I’m working on a workflow to center text in an image element. I’m using a python scrypt that calculates the length of the text (which is a dynamic variable), its center and, based on that, the coordinates to be entered in the “edit image” node to position my text always centered in a rectangle present on the image.

The script works, but only using the default font of the Python resource I’m using: Pill. But this font is too different from the one used in the image node and the result is not good.

I’ve tried giving the path (ID) of the font used in the node but it doesn’t work.

How can I load a font from n8n into the code node and use it in my python script?

Please share your workflow

{
“nodes”: [
{
“parameters”: {
“url”: “https://www.darts-nerd.com/wp-content/uploads/2025/01/BetMGM-Premier-League-Flechette-Avant-Match.webp”,
“options”: {}
},
“id”: “023e841e-8c98-4c3a-84c7-052260abf56b”,
“name”: “Mockup - Premier League2”,
“type”: “n8n-nodes-base.httpRequest”,
“typeVersion”: 4.2,
“position”: [
1140,
2460
]
},
{
“parameters”: {
“language”: “python”,
“pythonCode”: “from PIL import ImageFont, ImageDraw, Image\n\ndef calculate_text_position(center_x, center_y, text, font):\n """\n Calcule les coordonnées pour centrer dynamiquement un texte autour d’un point donné.\n Les coordonnées renvoyées placent le texte de manière à ce que son centre soit aligné avec (center_x, center_y).\n """\n # Calculer les dimensions précises du texte avec textsize\n text_width, text_height = font.getsize(text)\n\n # Calculer les coordonnées pour centrer le texte\n x = center_x - (text_width // 2)\n y = center_y - (text_height // 2)\n\n return x, y\n\n# Charger une police spécifique (Arial Bold taille 50)\ndef load_font():\n try:\n return ImageFont.truetype("/var/lib/docker/overlay2/f87a5096df04dac3defe18ae520d1440cb8b86f21382135e186e77cc364de806/diff/usr/share/fonts/truetype/msttcorefonts/Arial_Bold.ttf", 50) # Arial Bold en taille 50\n except OSError:\n return ImageFont.load_default() # Repli sur la police par défaut si Arial Bold n’est pas disponible\n\nfont = load_font()\n\n# Variables input et output\nresult = \n\nfor item in _input.all():\n # Récupérer les données d’entrée\n fullName_a = item.json.get(‘joueur_a’, ‘’)\n fullName_b = item.json.get(‘joueur_b’, ‘’)\n\n phase = item.json.get(‘phase’, ‘’)\n date = item.json.get(‘date’, ‘’)\n tournois = item.json.get(‘tournois’, ‘’)\n\n year = date.split(‘/’)[-1] if date else ‘’\n\n firstName_a = fullName_a.split(’ ')[0] if fullName_a else ‘’\n lastName_a = ’ ‘.join(fullName_a.split(’ ‘)[1:]) if len(fullName_a.split(’ ‘)) > 1 else ‘’\n\n firstName_b = fullName_b.split(’ ')[0] if fullName_b else ‘’\n lastName_b = ’ ‘.join(fullName_b.split(’ ‘)[1:]) if len(fullName_b.split(’ ')) > 1 else ‘’\n\n # Coordonnées des centres ajustés pour chaque texte\n center_x = 228\n firstName_a_y = 320 # Légèrement au-dessus du centre\n lastName_a_y = 400 # Légèrement en-dessous du centre\n\n # Calculer les coordonnées pour chaque texte\n x_firstName_a, y_firstName_a = calculate_text_position(center_x, firstName_a_y, firstName_a, font)\n x_lastName_a, y_lastName_a = calculate_text_position(center_x, lastName_a_y, lastName_a, font)\n\n x_firstName_b, y_firstName_b = calculate_text_position(center_x, firstName_a_y, firstName_b, font)\n x_lastName_b, y_lastName_b = calculate_text_position(center_x, lastName_a_y, lastName_b, font)\n\n # Ajouter les résultats au tableau final avec toutes les données\n result.append({\n "json": {\n "firstName_a": firstName_a,\n "lastName_a": lastName_a,\n "x_firstName_a": x_firstName_a,\n "y_firstName_a": y_firstName_a,\n "x_lastName_a": x_lastName_a,\n "y_lastName_a": y_lastName_a,\n "firstName_b": firstName_b,\n "lastName_b": lastName_b,\n "x_firstName_b": x_firstName_b,\n "y_firstName_b": y_firstName_b,\n "x_lastName_b": x_lastName_b,\n "y_lastName_b": y_lastName_b,\n "phase": phase,\n "year": year,\n "tournois": tournois\n }\n })\n\nreturn result\n”
},
“type”: “n8n-nodes-base.code”,
“typeVersion”: 2,
“position”: [
900,
2460
],
“id”: “23e858ad-724d-4127-b41b-d1149de990dd”,
“name”: “Formatage - Premier League1”
},
{
“parameters”: {
“operation”: “multiStep”,
“operations”: {
“operations”: [
{
“operation”: “text”,
“text”: “={{ $json.firstName_a }}”,
“fontSize”: 50,
“fontColor”: “#FFFFFF”,
“positionX”: “={{ $json.x_firstName_a }}”,
“positionY”: “={{ $json.y_firstName_a }}”,
“font”: “=/usr/share/fonts/truetype/msttcorefonts/Arial_Bold.ttf”
}
]
},
“options”: {}
},
“type”: “n8n-nodes-base.editImage”,
“typeVersion”: 1,
“position”: [
1400,
2460
],
“id”: “f9ecad60-1537-47f9-a7dd-82449e796340”,
“name”: “Edit Image2”
}
],
“connections”: {
“Mockup - Premier League2”: {
“main”: [
[
{
“node”: “Edit Image2”,
“type”: “main”,
“index”: 0
}
]
]
},
“Formatage - Premier League1”: {
“main”: [

]
},
“Edit Image2”: {
“main”: [

]
}
},
“pinData”: {}
}

Share the output returned by the last node

“{
“errorMessage”: “OSError: cannot open resource\n”,
“errorDetails”: {},
“n8nDetails”: {
“nodeName”: “Formatage - Premier League1”,
“nodeType”: “n8n-nodes-base.code”,
“nodeVersion”: 2,
“n8nVersion”: “1.73.1 (Self Hosted)”,
“binaryDataMode”: “default”,
“stackTrace”: [
“Error: OSError: cannot open resource”,
“”,
" at PythonSandbox.getPrettyError (/usr/local/lib/node_modules/n8n/node_modules/n8n-nodes-base/dist/nodes/Code/PythonSandbox.js:73:20)”,
" at PythonSandbox.runCodeInPython (/usr/local/lib/node_modules/n8n/node_modules/n8n-nodes-base/dist/nodes/Code/PythonSandbox.js:60:24)“,
" at PythonSandbox.runCodeAllItems (/usr/local/lib/node_modules/n8n/node_modules/n8n-nodes-base/dist/nodes/Code/PythonSandbox.js:26:33)”,
" at ExecuteContext.execute (/usr/local/lib/node_modules/n8n/node_modules/n8n-nodes-base/dist/nodes/Code/Code.node.js:132:26)“,
" at WorkflowExecute.runNode (/usr/local/lib/node_modules/n8n/node_modules/n8n-core/dist/WorkflowExecute.js:634:19)”,
" at /usr/local/lib/node_modules/n8n/node_modules/n8n-core/dist/WorkflowExecute.js:874:51",
" at /usr/local/lib/node_modules/n8n/node_modules/n8n-core/dist/WorkflowExecute.js:1305:20"
]
}
}"

Information on your n8n setup

  • n8n version: 1.73.1
  • Database default: SQLite
  • n8n EXECUTIONS_PROCESS setting (default: own, main):?
  • Running n8n via: Docker, Coolify
  • Operating system: Ubuntu

It looks like your topic is missing some important information. Could you provide the following if applicable.

  • n8n version:
  • Database (default: SQLite):
  • n8n EXECUTIONS_PROCESS setting (default: own, main):
  • Running n8n via (Docker, npm, n8n cloud, desktop app):
  • Operating system:
  • n8n version: 1.73.1
  • Database default: SQLite
  • n8n EXECUTIONS_PROCESS setting (default: own, main):?
  • Running n8n via: Docker, Coolify
  • Operating system: Ubuntu

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.