AI Avatar Tool

How to Build an AI Avatar Tool Easy Step-by-Step Guide

final output

In this artical, we will build a simple AI Avatar tool that allows users to upload an image, select an avatar style, and generate a new AI avatar for there Social appearances. The application will use React , FastAPI , and AI model for image generation, so you don’t need a powerful GPU on your computer. Soo Lets start

Here are what we are building:
complete work flow

User
↓
Upload Image
↓
Select Avatar Style
↓
React
↓
FastAPI
↓
Cloud AI Model
↓
Generated Avatar
↓
Download

AI Model

So for this we are using fal.ai for this tool somehow you can use Hugging Face ,Replicate , Google Gemini image models , Together AI.
The main reason i am using fal because it gives free $5 credits on account creation that is why i am using this model

fal.ai dashboard
Fal.ai Dashboard
  • Create an account.
  • Generate an API key.
  • Save the key.

Create the AI-avatar tool

  • Create the Project

First of all you have a create a project in which there are main project name like ai-avatar-tool > backend and frondend
folders

folders structure

next we have to install the react and python on the folders like in frontend we have to install the

npm create vite@latest frontend

using this command we can install the react in the folder
and then in the backend > main.py

python -m venv venv
venv\Scripts\activate
pip install fastapi uvicorn python-multipart pillow fal-client requests

after that we have to configure the api key in the powershell you can also add the api key in the code

$env:FAL_KEY="YOUR_FAL_KEY"

and this is the backend > main.py code


import os
import io
import base64
import asyncio

from fastapi import FastAPI, HTTPException, UploadFile, File, Form
from fastapi.middleware.cors import CORSMiddleware
from PIL import Image
import fal_client

app = FastAPI(title="AI Avatar Generator")

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

FAL_KEY = os.getenv("FAL_KEY")

if not FAL_KEY:
    print("WARNING: FAL_KEY environment variable is not set.")

os.environ["FAL_KEY"] = FAL_KEY or ""

MODEL = "fal-ai/flux-kontext/dev"


@app.get("/")
def read_root():
    return {
        "status": "AI Avatar Backend Active",
        "model": MODEL
    }


@app.post("/generate-avatar")
async def generate_avatar(
    prompt: str = Form(...),
    file: UploadFile = File(...)
):
    if not FAL_KEY:
        raise HTTPException(
            status_code=500,
            detail="FAL_KEY is not configured on the server."
        )

    if not file.content_type or not file.content_type.startswith("image/"):
        raise HTTPException(
            status_code=400,
            detail="Please upload a valid image."
        )

    try:
        image_bytes = await file.read()

        if not image_bytes:
            raise HTTPException(
                status_code=400,
                detail="Uploaded image is empty."
            )

        if len(image_bytes) > 10 * 1024 * 1024:
            raise HTTPException(
                status_code=400,
                detail="Image must be smaller than 10MB."
            )

        try:
            image = Image.open(io.BytesIO(image_bytes)).convert("RGB")
        except Exception:
            raise HTTPException(
                status_code=400,
                detail="Unable to read the uploaded image."
            )

        image.thumbnail((1024, 1024))

        buffer = io.BytesIO()
        image.save(buffer, format="JPEG", quality=90)
        buffer.seek(0)

        print("Uploading image to fal.ai...")

        image_url = await asyncio.to_thread(
            fal_client.upload,
            buffer.getvalue(),
            "image/jpeg"
        )

        final_prompt = f"""
Use the uploaded image as the primary visual and identity reference.

Transform the person in the uploaded image into a professional AI avatar.

Preserve the person's recognizable identity, facial structure,
face shape, eyes, nose, lips, hairstyle, skin tone, age appearance,
and natural facial proportions.

Do not turn the person into a different person.
Do not unnecessarily change their facial identity.

Apply this artistic style:

{prompt}

The person's face should remain clearly recognizable.
Create a polished high-quality portrait.
Sharp facial details.
Natural anatomy.
Professional composition.
Cinematic lighting.
Detailed rendering.
Clean background.
High-quality AI avatar.
"""

        print("Generating avatar with fal.ai...")
        print(f"Style: {prompt}")

        result = await asyncio.to_thread(
            fal_client.run,
            MODEL,
            arguments={
                "prompt": final_prompt,
                "image_url": image_url,
                "aspect_ratio": "1:1",
                "output_format": "png",
                "guidance_scale": 3.5,
                "num_images": 1
            }
        )

        print("fal.ai generation completed.")

        images = result.get("images", [])

        if not images:
            raise Exception("fal.ai did not return an image.")

        generated_url = images[0].get("url")

        if not generated_url:
            raise Exception("Generated image URL was not returned.")

        import requests

        generated_response = await asyncio.to_thread(
            requests.get,
            generated_url,
            timeout=60
        )

        if generated_response.status_code != 200:
            raise Exception(
                f"Could not download generated image: "
                f"{generated_response.status_code}"
            )

        output_base64 = base64.b64encode(
            generated_response.content
        ).decode("utf-8")

        return {
            "success": True,
            "avatar": f"data:image/png;base64,{output_base64}",
            "model": MODEL
        }

    except HTTPException:
        raise

    except Exception as e:
        print("Avatar generation error:", str(e))

        raise HTTPException(
            status_code=500,
            detail=f"Avatar generation failed: {str(e)}"
        )

this is our main prompt to make the image to avatar

 final_prompt = f”””

Use the uploaded image as the primary visual and identity reference.

Transform the person in the uploaded image into a professional AI avatar.

Preserve the person’s recognizable identity, facial structure,

face shape, eyes, nose, lips, hairstyle, skin tone, age appearance,

and natural facial proportions.

Do not turn the person into a different person.

Do not unnecessarily change their facial identity.

Apply this artistic style:

{prompt}

The person’s face should remain clearly recognizable.

Create a polished high-quality portrait.

Sharp facial details.

Natural anatomy.

Professional composition.

Cinematic lighting.

Detailed rendering.

Clean background.

High-quality AI avatar.

“””
you can change it according to your then this is app.jsx code for the tool.

import React, { useState } from "react";

const styles = [
  {
    name: "Oil Painting",
    prompt:
      "Transform the person into a premium classical oil painting avatar. Elegant realistic brushwork, rich painterly textures, sophisticated lighting, subtle canvas texture, museum-quality portrait."
  },
  {
    name: "Cyberpunk",
    prompt:
      "Transform the person into a futuristic cyberpunk avatar. Neon blue and magenta lighting, futuristic city atmosphere, subtle technological details, cinematic rim lighting, sharp facial details, premium digital artwork."
  },
  {
    name: "3D Animated",
    prompt:
      "Transform the person into a high-quality 3D animated character avatar. Stylized but natural proportions, expressive eyes, smooth detailed 3D materials, cinematic studio lighting, polished animated character rendering."
  },
  {
    name: "Anime",
    prompt:
      "Transform the person into a premium anime-style avatar. Detailed anime facial design, clean linework, expressive eyes, beautiful cel shading, cinematic lighting, polished digital illustration, vibrant balanced colors."
  },
  {
    name: "Comic Book",
    prompt:
      "Transform the person into a high-end comic book character avatar. Bold ink outlines, detailed facial features, dynamic comic-book shading, dramatic cinematic lighting, subtle halftone texture, rich colors."
  },
  {
    name: "Marble Statue",
    prompt:
      "Transform the person into a highly detailed classical Greek marble bust. White Carrara marble texture, realistic sculpted details, elegant classical proportions, subtle stone imperfections, museum-quality sculpture."
  },
  {
    name: "Fantasy Warrior",
    prompt:
      "Transform the person into an epic fantasy warrior avatar. Detailed fantasy armor, cinematic lighting, dramatic atmosphere, realistic textures, subtle magical elements, powerful character presence, premium cinematic concept art."
  },
  {
    name: "Royal Portrait",
    prompt:
      "Transform the person into an elegant royal portrait. Luxurious royal clothing, sophisticated historical styling, rich fabric textures, elegant studio lighting, classical composition, refined color grading."
  },
  {
    name: "Futuristic AI",
    prompt:
      "Transform the person into a sophisticated futuristic AI avatar. Sleek futuristic design, subtle holographic elements, advanced technology aesthetic, cinematic lighting, realistic skin texture, premium sci-fi character portrait."
  },
  {
    name: "Professional",
    prompt:
      "Transform the person into a premium professional profile avatar. Professional studio photography, soft cinematic lighting, clean elegant background, realistic skin texture, sharp eyes, natural expression, polished appearance."
  }
];

export default function App() {
  const [file, setFile] = useState(null);
  const [selectedStyle, setSelectedStyle] = useState(styles[0]);
  const [avatarSrc, setAvatarSrc] = useState(null);
  const [previewSrc, setPreviewSrc] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState("");

  const handleFileChange = (event) => {
    const selectedFile = event.target.files?.[0];

    if (!selectedFile) {
      return;
    }

    if (!selectedFile.type.startsWith("image/")) {
      setError("Please select a valid image.");
      return;
    }

    if (selectedFile.size > 10 * 1024 * 1024) {
      setError("Image must be smaller than 10MB.");
      return;
    }

    setFile(selectedFile);
    setError("");
    setAvatarSrc(null);

    const reader = new FileReader();

    reader.onload = () => {
      setPreviewSrc(reader.result);
    };

    reader.readAsDataURL(selectedFile);
  };

  const handleGenerate = async () => {
    if (!file) {
      setError("Please upload a photo first.");
      return;
    }

    setLoading(true);
    setError("");
    setAvatarSrc(null);

    const formData = new FormData();

    formData.append("file", file);
    formData.append("prompt", selectedStyle.prompt);

    try {
      const response = await fetch(
        "http://127.0.0.1:8000/generate-avatar",
        {
          method: "POST",
          body: formData
        }
      );

      const data = await response.json();

      if (!response.ok) {
        throw new Error(
          data.detail || `Server error: ${response.status}`
        );
      }

      if (!data.avatar) {
        throw new Error("The server did not return an avatar.");
      }

      setAvatarSrc(data.avatar);
    } catch (err) {
      console.error(err);

      setError(
        err.message ||
          "Failed to generate avatar. Please check your FastAPI server."
      );
    } finally {
      setLoading(false);
    }
  };

  const handleDownload = () => {
    if (!avatarSrc) {
      return;
    }

    const link = document.createElement("a");

    link.href = avatarSrc;
    link.download = "ai-avatar.png";

    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
  };

  return (
    <div
      style={{
        minHeight: "100vh",
        background: "#f5f7fb",
        padding: "40px 20px",
        fontFamily: "Arial, sans-serif"
      }}
    >
      <div
        style={{
          maxWidth: "850px",
          margin: "0 auto",
          background: "#ffffff",
          borderRadius: "18px",
          padding: "30px",
          boxShadow: "0 10px 35px rgba(0,0,0,0.08)"
        }}
      >
        <h1
          style={{
            textAlign: "center",
            marginBottom: "8px"
          }}
        >
          AI Avatar Generator
        </h1>

        <p
          style={{
            textAlign: "center",
            color: "#666",
            marginBottom: "30px"
          }}
        >
          Upload your photo and transform it into an AI avatar.
        </p>

        <div
          style={{
            border: "2px dashed #d5d9e2",
            borderRadius: "14px",
            padding: "30px",
            textAlign: "center",
            marginBottom: "30px"
          }}
        >
          <h3>1. Upload Your Photo</h3>

          <input
            type="file"
            accept="image/png,image/jpeg,image/webp"
            onChange={handleFileChange}
          />

          {previewSrc && (
            <div style={{ marginTop: "20px" }}>
              <img
                src={previewSrc}
                alt="Uploaded"
                style={{
                  width: "180px",
                  height: "180px",
                  objectFit: "cover",
                  borderRadius: "12px",
                  border: "1px solid #ddd"
                }}
              />

              <p
                style={{
                  fontSize: "13px",
                  color: "#555"
                }}
              >
                {file?.name}
              </p>
            </div>
          )}
        </div>

        <div style={{ marginBottom: "30px" }}>
          <h3>2. Choose Avatar Style</h3>

          <div
            style={{
              display: "grid",
              gridTemplateColumns:
                "repeat(auto-fit, minmax(150px, 1fr))",
              gap: "10px"
            }}
          >
            {styles.map((style) => {
              const active =
                selectedStyle.name === style.name;

              return (
                <button
                  key={style.name}
                  onClick={() => setSelectedStyle(style)}
                  style={{
                    padding: "14px 10px",
                    borderRadius: "10px",
                    border: active
                      ? "2px solid #2563eb"
                      : "1px solid #ddd",
                    background: active
                      ? "#eff6ff"
                      : "#ffffff",
                    color: "#222",
                    cursor: "pointer",
                    fontWeight: active ? "bold" : "normal"
                  }}
                >
                  {style.name}
                </button>
              );
            })}
          </div>
        </div>

        <div
          style={{
            background: "#f8fafc",
            padding: "15px",
            borderRadius: "10px",
            marginBottom: "25px"
          }}
        >
          <strong>Selected style:</strong>{" "}
          {selectedStyle.name}
        </div>

        <button
          onClick={handleGenerate}
          disabled={loading || !file}
          style={{
            width: "100%",
            padding: "16px",
            border: "none",
            borderRadius: "10px",
            background:
              loading || !file ? "#9ca3af" : "#2563eb",
            color: "#ffffff",
            fontSize: "17px",
            fontWeight: "bold",
            cursor:
              loading || !file
                ? "not-allowed"
                : "pointer"
          }}
        >
          {loading
            ? "Generating AI Avatar..."
            : "Generate AI Avatar"}
        </button>

        {error && (
          <div
            style={{
              marginTop: "20px",
              padding: "12px",
              borderRadius: "8px",
              background: "#fee2e2",
              color: "#b91c1c"
            }}
          >
            {error}
          </div>
        )}

        {loading && (
          <div
            style={{
              textAlign: "center",
              marginTop: "30px",
              color: "#555"
            }}
          >
            <p>
              AI is transforming your photo...
            </p>

            <p style={{ fontSize: "13px" }}>
              This may take a little while because the
              image is being generated in the cloud.
            </p>
          </div>
        )}

        {avatarSrc && !loading && (
          <div
            style={{
              marginTop: "35px",
              textAlign: "center"
            }}
          >
            <h2>Your AI Avatar</h2>

            <img
              src={avatarSrc}
              alt="Generated AI Avatar"
              style={{
                width: "350px",
                height: "350px",
                maxWidth: "100%",
                objectFit: "cover",
                borderRadius: "20px",
                border: "5px solid #ffffff",
                boxShadow:
                  "0 10px 30px rgba(0,0,0,0.15)"
              }}
            />

            <div style={{ marginTop: "20px" }}>
              <button
                onClick={handleDownload}
                style={{
                  padding: "12px 25px",
                  border: "none",
                  borderRadius: "8px",
                  background: "#16a34a",
                  color: "#ffffff",
                  fontSize: "15px",
                  fontWeight: "bold",
                  cursor: "pointer"
                }}
              >
                Download Avatar
              </button>
            </div>
          </div>
        )}
      </div>
    </div>
  );
}
const styles = [

  {

    name: "Oil Painting",

    prompt:

      "Transform the person into a premium classical oil painting avatar. Elegant realistic brushwork, rich painterly textures, sophisticated lighting, subtle canvas texture, museum-quality portrait."

  },

  {

    name: "Cyberpunk",

    prompt:

      "Transform the person into a futuristic cyberpunk avatar. Neon blue and magenta lighting, futuristic city atmosphere, subtle technological details, cinematic rim lighting, sharp facial details, premium digital artwork."

  },

  {

    name: "3D Animated",

    prompt:

      "Transform the person into a high-quality 3D animated character avatar. Stylized but natural proportions, expressive eyes, smooth detailed 3D materials, cinematic studio lighting, polished animated character rendering."

  },

  {

    name: "Anime",

    prompt:

      "Transform the person into a premium anime-style avatar. Detailed anime facial design, clean linework, expressive eyes, beautiful cel shading, cinematic lighting, polished digital illustration, vibrant balanced colors."

  },

  {

    name: "Comic Book",

    prompt:

      "Transform the person into a high-end comic book character avatar. Bold ink outlines, detailed facial features, dynamic comic-book shading, dramatic cinematic lighting, subtle halftone texture, rich colors."

  },

  {

    name: "Marble Statue",

    prompt:

      "Transform the person into a highly detailed classical Greek marble bust. White Carrara marble texture, realistic sculpted details, elegant classical proportions, subtle stone imperfections, museum-quality sculpture."

  },

  {

    name: "Fantasy Warrior",

    prompt:

      "Transform the person into an epic fantasy warrior avatar. Detailed fantasy armor, cinematic lighting, dramatic atmosphere, realistic textures, subtle magical elements, powerful character presence, premium cinematic concept art."

  },

  {

    name: "Royal Portrait",

    prompt:

      "Transform the person into an elegant royal portrait. Luxurious royal clothing, sophisticated historical styling, rich fabric textures, elegant studio lighting, classical composition, refined color grading."

  },

  {

    name: "Futuristic AI",

    prompt:

      "Transform the person into a sophisticated futuristic AI avatar. Sleek futuristic design, subtle holographic elements, advanced technology aesthetic, cinematic lighting, realistic skin texture, premium sci-fi character portrait."

  },

  {

    name: "Professional",

    prompt:

      "Transform the person into a premium professional profile avatar. Professional studio photography, soft cinematic lighting, clean elegant background, realistic skin texture, sharp eyes, natural expression, polished appearance."

  }

];

these are your prompts thatwill be in select from the user

final output

Leave a Comment

Your email address will not be published. Required fields are marked *