DIY Deepfake Magic: Create Stunning Face Swaps from Home for Just $0.24/Hour

Hey there, fellow AI enthusiast! If you've ever dreamed of swapping faces in images like a pro—whether for fun creative projects, artistic experiments, or just to see what your face looks like in a movie scene—this guide is your ticket to deepfake wizardry. We're talking about a completely DIY setup using free tools like ComfyUI and the powerful ReActor node, all running on a budget cloud GPU from RunPod. No fancy hardware needed; you can do this from your home computer for pennies per hour.
The best part? It's stealthy, straightforward, and super affordable. We'll walk you through every step, from signing up to hitting "Run" on your first deepfake. Remember, with great power comes great responsibility—use these tools ethically, get consent for any faces involved, and stick to legal, positive uses like personal art or memes. Let's dive in and make some magic!
{{ARTICLE_ILLUSTATION}}
Step 1: Create Your RunPod Account – Your Gateway to Cloud Power
Getting started is a breeze. RunPod is a user-friendly platform that lets you rent GPUs on demand, perfect for AI tasks without breaking the bank. It's free to sign up, and you'll need a minimum of $10 in credits to begin (which gives you about 40+ hours on our recommended setup).
- Head over to the RunPod website and click "Sign Up" in the top right.
- Enter your email, create a password, and verify your account via the email link they send.
- Once logged in, you'll land on the dashboard. Add credits by clicking "Billing" > "Add Credits" – start with $10 to test the waters. (Pro tip: They often have referral bonuses if you search for one!)
- Familiarize yourself with the interface: The "Pods" section is where the action happens, and "Storage" lets you create persistent volumes to save your work across sessions.
From sources like the official RunPod docs and community guides on Medium, this setup ensures your models and workflows stick around even if you pause or terminate a pod. No more starting from scratch!
Step 2: Deploy Your Minimal Pod – Budget-Friendly GPU Rental
Now, let's spin up a pod. We're going for the RTX 2000 Ada GPU at just $0.24 per hour – powerful enough for deepfakes but gentle on your wallet. This card has 16GB VRAM, ideal for Stable Diffusion XL (SDXL) models and face swaps without lag.
- In the RunPod dashboard, click "Pods" > "Deploy."
- Choose your GPU: Search for "RTX 2000 Ada Generation" and select it. Pick a datacenter close to you (e.g., US-East for low latency).
- Template Selection: In the "Template" dropdown, search for "runpod/pytorch:2.8.0-py3.11-cuda12.8.1-cudnn-devel-ubuntu22.04." This pre-configured image comes with PyTorch 2.8, CUDA 12.8, and Python 3.11 – everything you need for ComfyUI without manual tweaks. (Confirmed in RunPod's PyTorch guide.)
- Storage Setup: Opt for a persistent 100GB Network Volume (about $7/month) to store models and outputs. Attach it to
/workspacefor easy access. This keeps your deepfake files safe even after the pod stops. - Ports: Expose these HTTP ports for connections:
- Port 8888: For JupyterLab (terminal and file management).
- Port 3000: For ComfyUI web interface.
- Advanced Options: Set auto-termination to 10-30 minutes of inactivity to save costs. Leave other settings default.
- Click "Deploy" – your pod will spin up in 1-2 minutes. Note the Pod ID (e.g., "abc123") from the dashboard; you'll need it for URLs.
Total setup cost? Under $1 for your first hour, including storage. As per Reddit tutorials like this persistent ComfyUI guide, this config is rock-solid for DIY deepfakes.
Highlight: Always monitor your pod's status in the dashboard. If it's "Stopped," just resume it to pick up where you left off.
Step 3: Connect to Your Pod via JupyterLab – Your Control Center
With the pod running (status: "Running"), it's time to connect. JupyterLab gives you a browser-based terminal and file explorer – no SSH hassle.
- In the Pods dashboard, click "Connect" next to your pod.
- Under "HTTP Services," find Port 8888 and click "Connect to HTTP Service [Port 8888]." This opens a new tab with the URL format:
https://[PodId]-8888.proxy.runpod.net/lab.- Example: If your Pod ID is "def456," it's
https://def456-8888.proxy.runpod.net/lab.
- Example: If your Pod ID is "def456," it's
- If prompted for a token, check the pod logs in the dashboard or run
jupyter server listin the web terminal (more on that below). Paste it in. - You'll see the JupyterLab interface: A file browser on the left, launcher in the center. Navigate to
/workspace– this is your working directory.
From RunPod's connection docs, this setup is secure and direct. If the page loads slowly, refresh or check your internet – it's proxy-based for safety.
Step 4: Open Terminal and Install Everything with Our Magic One-Liner
Time for the fun part: Installing ComfyUI, ReActor, and models. We'll use a single command block to clone repos, set up the environment, and download essentials. This takes 5-15 minutes, mostly for downloads.
- In JupyterLab, click "New" > "Terminal" (or right-click in the file browser and select "Open Terminal").
- Ensure you're in
/workspaceby typingcd /workspaceand pressing Enter. Verify withpwd. - Copy and paste this exact one-liner into the terminal (it's a chain of commands separated by
&&for sequential execution). Hit Enter and let it run – grab a coffee!
cd /workspace && git clone https://github.com/comfyanonymous/ComfyUI.git && cd ComfyUI && apt update && apt install -y build-essential && python -m venv venv && source venv/bin/activate && pip install --upgrade pip && pip install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu128 && pip install -r requirements.txt && cd custom_nodes && git clone https://github.com/Gourieff/comfyui-reactor-node.git && cd comfyui-reactor-node && pip install insightface==0.7.3 && python install.py && mkdir -p ../../models/insightface/models/antelopev2 && wget -O ../../models/insightface/models/antelopev2/inswapper_128.onnx https://huggingface.co/ezioruan/inswapper_128.onnx/resolve/main/inswapper_128.onnx && cd ../../models/facerestore_models && wget -O codeformer-v0.1.0.pth https://github.com/sczhou/CodeFormer/releases/download/v0.1.0/codeformer.pth && cd ../checkpoints && wget -O sd_xl_base_1.0.safetensors https://huggingface.co/stabilityai/stable-diffusion-xl-base-1.0/resolve/main/sd_xl_base_1.0.safetensors && cd ../vae && wget -O sdxl_vae.safetensors https://huggingface.co/stabilityai/sdxl-vae/resolve/main/sdxl_vae.safetensors && cd /workspace/ComfyUI
What this does, step by step:
- Clones ComfyUI from GitHub.
- Updates packages and installs build tools.
- Creates a virtual environment for isolation.
- Installs PyTorch (CUDA 12.8 compatible), ComfyUI requirements.
- Clones and installs ReActor node from Gourieff's repo, including Insightface for face detection.
- Downloads key models:
- Inswapper_128.onnx (~246MB): Core face swap model.
- CodeFormer (~540MB): Face restoration for clean results.
- SDXL Base (~6.9GB): Text-to-image generation.
- SDXL VAE (~335MB): Image decoding.
- Returns to ComfyUI root.
If it errors (e.g., on apt), try prefixing with sudo. Downloads use ~10GB total – ensure your volume has space. Sourced from aggregated tutorials like this GitHub install guide and YouTube setups.
Highlight: Run source venv/bin/activate in future sessions to reactivate the environment.
Step 5: Uncensor ReActor for Full Freedom – A Quick Edit
By default, ReActor has an NSFW filter to prevent misuse. For unrestricted creative use (remember ethics!), we'll disable it stealthily.
- In JupyterLab's file browser, navigate to
/workspace/ComfyUI/custom_nodes/comfyui-reactor-node/scripts/. - Right-click
reactor_sfw.py> "Open With" > "Editor" (or use terminal:nano reactor_sfw.py). - Find the function
def nsfw_image(...)(around line 10-20). At the very beginning of the function, add:return False.- Example edit:
def nsfw_image(image: Image.Image, score_threshold: float = 0.5): return False # Bypass NSFW check # Original code below...
- Example edit:
- Save the file (Ctrl+S in editor or Ctrl+O in nano, then Enter and Ctrl+X).
This forces the function to always return False, skipping detection. From Reddit guides and YouTube fixes, it's a simple, effective tweak. Use responsibly – this removes safeguards!
Step 6: Launch and Restart ComfyUI – Your Deepfake Canvas Awaits
-
Start ComfyUI: In the terminal (with venv activated), run:
cd /workspace/ComfyUI && source venv/bin/activate && python main.py --listen 0.0.0.0 --port 3000You'll see logs like "Starting server" and "To see the GUI go to: http://0.0.0.0:3000."
-
In a new browser tab, go to
https://[PodId]-3000.proxy.runpod.net/(e.g.,https://def456-3000.proxy.runpod.net/). -
The ComfyUI interface loads – a clean node graph editor. If it's glitchy, restart:
- In terminal: Ctrl+C to stop, then re-run the start command.
- Or use the menu: In ComfyUI, go to "Menu" > "Restart" (if available), or kill the process with
fuser -k 3000/tcpand restart.
From RunPod's ComfyUI tutorial, port 3000 is standard for proxies. You're now in the node-based playground!
Highlight: Bookmark this URL – it's your session's heart.
Step 7: Load the Workflow – The Heart of Your Deepfake
ComfyUI uses JSON workflows for repeatable magic. We've prepared a minimal one for text-to-image generation followed by face swap: Generate a base image from a prompt, then swap in your source face.
- In ComfyUI, click "Load" (top right) > "Load Default" or drag-drop, but instead, copy the entire JSON below.
- Paste it into a text file in JupyterLab (New > Text File), save as
deepfake_workflow.jsonin/workspace/ComfyUI. - Back in ComfyUI, click "Load" and select the file. Nodes will populate: Checkpoint loader, prompts, sampler, ReActor swap, and save.
Here's the complete JSON workflow – copy it exactly:
{
"id": "minimal-reactor-workflow",
"revision": 0,
"last_node_id": 10,
"last_link_id": 14,
"nodes": [
{
"id": 1,
"type": "CheckpointLoaderSimple",
"pos": [100, 100],
"size": [270, 98],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [],
"outputs": [
{"name": "MODEL", "type": "MODEL", "links": [1]},
{"name": "CLIP", "type": "CLIP", "links": [2, 3]},
{"name": "VAE", "type": "VAE", "links": [4]}
],
"properties": {"cnr_id": "comfy-core", "ver": "0.3.41", "Node name for S&R": "CheckpointLoaderSimple"},
"widgets_values": ["sd_xl_base_1.0.safetensors"]
},
{
"id": 2,
"type": "CLIPTextEncode",
"pos": [400, 100],
"size": [400, 200],
"flags": {},
"order": 1,
"mode": 0,
"inputs": [{"name": "clip", "type": "CLIP", "link": 2}],
"outputs": [{"name": "CONDITIONING", "type": "CONDITIONING", "links": [5]}],
"properties": {"cnr_id": "comfy-core", "ver": "0.3.41", "Node name for S&R": "CLIPTextEncode"},
"widgets_values": ["a beautiful landscape, mountains, river, sunset"]
},
{
"id": 3,
"type": "CLIPTextEncode",
"pos": [400, 350],
"size": [400, 200],
"flags": {},
"order": 2,
"mode": 0,
"inputs": [{"name": "clip", "type": "CLIP", "link": 3}],
"outputs": [{"name": "CONDITIONING", "type": "CONDITIONING", "links": [6]}],
"properties": {"cnr_id": "comfy-core", "ver": "0.3.41", "Node name for S&R": "CLIPTextEncode"},
"widgets_values": ["blurry, low quality, artifacts"]
},
{
"id": 4,
"type": "EmptyLatentImage",
"pos": [100, 250],
"size": [270, 106],
"flags": {},
"order": 3,
"mode": 0,
"inputs": [],
"outputs": [{"name": "LATENT", "type": "LATENT", "links": [7]}],
"properties": {"cnr_id": "comfy-core", "ver": "0.3.41", "Node name for S&R": "EmptyLatentImage"},
"widgets_values": [1024, 1024, 1]
},
{
"id": 5,
"type": "KSampler",
"pos": [850, 100],
"size": [270, 262],
"flags": {},
"order": 4,
"mode": 0,
"inputs": [
{"name": "model", "type": "MODEL", "link": 1},
{"name": "positive", "type": "CONDITIONING", "link": 5},
{"name": "negative", "type": "CONDITIONING", "link": 6},
{"name": "latent_image", "type": "LATENT", "link": 7}
],
"outputs": [{"name": "LATENT", "type": "LATENT", "links": [8]}],
"properties": {"cnr_id": "comfy-core", "ver": "0.3.41", "Node name for S&R": "KSampler"},
"widgets_values": [156680208522230, "randomize", 20, 1, "euler", "normal", 1]
},
{
"id": 6,
"type": "VAEDecode",
"pos": [1150, 100],
"size": [147, 46],
"flags": {},
"order": 5,
"mode": 0,
"inputs": [
{"name": "samples", "type": "LATENT", "link": 8},
{"name": "vae", "type": "VAE", "link": 4}
],
"outputs": [{"name": "IMAGE", "type": "IMAGE", "links": [9]}],
"properties": {"cnr_id": "comfy-core", "ver": "0.3.41", "Node name for S&R": "VAEDecode"},
"widgets_values": []
},
{
"id": 7,
"type": "LoadImage",
"pos": [100, 400],
"size": [340, 314],
"flags": {},
"order": 6,
"mode": 0,
"inputs": [],
"outputs": [
{"name": "IMAGE", "type": "IMAGE", "links": [10]},
{"name": "MASK", "type": "MASK", "links": null}
],
"properties": {"cnr_id": "comfy-core", "ver": "0.3.41", "Node name for S&R": "LoadImage"},
"widgets_values": ["source_face_image.png", "image"]
},
{
"id": 8,
"type": "ReActorFaceSwap",
"pos": [1350, 100],
"size": [285, 358],
"flags": {},
"order": 7,
"mode": 0,
"inputs": [
{"name": "input_image", "type": "IMAGE", "link": 9},
{"name": "source_image", "type": "IMAGE", "link": 10},
{"name": "face_model", "type": "FACE_MODEL", "link": null},
{"name": "face_boost", "type": "FACE_BOOST", "link": null}
],
"outputs": [
{"name": "SWAPPED_IMAGE", "type": "IMAGE", "links": [11]},
{"name": "FACE_MODEL", "type": "FACE_MODEL", "links": null},
{"name": "ORIGINAL_IMAGE", "type": "IMAGE", "links": null}
],
"properties": {"cnr_id": "comfyui-reactor", "ver": "48a3ad27f99f775dcf63e61276e0110d256597ef", "Node name for S&R": "ReActorFaceSwap"},
"widgets_values": [true, "inswapper_128.onnx", "retinaface_resnet50", "codeformer-v0.1.0.pth", 1, 1, "no", "no", "0", "0", 1]
},
{
"id": 9,
"type": "SaveImage",
"pos": [1650, 100],
"size": [308, 270],
"flags": {},
"order": 8,
"mode": 0,
"inputs": [{"name": "images", "type": "IMAGE", "link": 11}],
"outputs": [],
"properties": {"cnr_id": "comfy-core", "ver": "0.3.41", "Node name for S&R": "SaveImage"},
"widgets_values": ["ComfyUI"]
}
],
"links": [
[1, 1, 0, 5, 0, "MODEL"],
[2, 1, 1, 2, 0, "CLIP"],
[3, 1, 1, 3, 0, "CLIP"],
[4, 1, 2, 6, 1, "VAE"],
[5, 2, 0, 5, 1, "CONDITIONING"],
[6, 3, 0, 5, 2, "CONDITIONING"],
[7, 4, 0, 5, 3, "LATENT"],
[8, 5, 0, 6, 0, "LATENT"],
[9, 6, 0, 8, 0, "IMAGE"],
[10, 7, 0, 8, 1, "IMAGE"],
[11, 8, 0, 9, 0, "IMAGE"]
],
"groups": [],
"config": {},
"extra": {},
"version": 0.4
}
This workflow generates a 1024x1024 image from text, decodes it, swaps the face with your input, and saves the result. Customize nodes by double-clicking (e.g., change prompts).
Step 8: Choose Your Input Image and Prompt – Personalize the Magic
- Upload Source Face: In JupyterLab, go to
/workspace/ComfyUI/input/(create if needed). Drag-drop your source image (e.g., a clear face photo namedsource_face_image.png). In the workflow, double-click the "LoadImage" node (ID 7) and select it from the dropdown. - Set Your Prompt: Double-click the positive "CLIPTextEncode" node (ID 2). Replace the example with something fun, like "a portrait of a person in a fantasy world, detailed face, high quality." Negative prompt (ID 3): Keep as is or add "distorted, ugly."
- Tweak Settings: In "EmptyLatentImage" (ID 4), adjust width/height for your needs (start at 1024x1024). In "KSampler" (ID 5), set steps to 20-30 for quality.
Pro tip: For better deepfakes, use high-res, front-facing source images. Sources like ReActor's GitHub recommend clear lighting.
Step 9: Hit Run and Watch the Deepfake Unfold
- Click "Queue Prompt" (big green button in ComfyUI).
- Progress shows in the sidebar – sampling takes 10-30 seconds, swap another 5.
- Output appears in
/workspace/ComfyUI/output/– download via JupyterLab or right-click in ComfyUI.
Boom! Your first deepfake. Experiment: Chain workflows for video (add AnimateDiff nodes) or refine with masks in ReActor.
Highlight: Each run costs ~$0.01-0.05. Pause the pod when done to stop the clock.
Troubleshooting Common Hiccups
- Pod Won't Start: Check credits/billing. Try a different datacenter.
- Download Fails: Rerun wget with
--continueor check internet. Uselsto verify files. - ReActor Errors: Reinstall Insightface:
pip install insightface==0.7.3. Ensure models in paths. - Black/NSFW Blocked Images: Confirm the sfw.py edit; restart ComfyUI.
- VRAM Out of Memory: Lower resolution to 512x512 or add
--lowvramto main.py. - Jupyter Token Issues: From docs, run
jupyter lab --generate-configand set a password, or use web terminal.
For more, check ComfyUI GitHub issues.
Frequently Asked Questions
Q: Is this legal/safe?
A: Absolutely for ethical uses! Deepfakes are tools like Photoshop – consent and laws matter. Avoid sharing harmful content.
Q: Can I do video deepfakes?
A: Yes! Extend with nodes like LoadVideo and frame-by-frame ReActor. Tutorials on Toolify AI guide you.
Q: How do I save workflows/models?
A: Network Volumes persist everything. Export workflows as JSON via "Save."
Q: Faster/cheaper alternatives?
A: Local PC if you have a GPU, but RunPod's $0.24/hr beats most. Scale to serverless for batches.
Q: Add more features?
A: Install ComfyUI-Manager: git clone https://github.com/ltdrdata/ComfyUI-Manager.git in custom_nodes, then restart.
There you have it – your home deepfake studio, stealthy and affordable. Experiment, create responsibly, and share your cool (ethical) results in the comments. Happy swapping! 🚀