API per la ricerca tramite volto

Dai ai tuoi utenti la possibilità di cercare su internet partendo da un volto! Integra la ricerca facciale di FaceCheck nella tua app, sito o piattaforma.

Le nostre API REST sono semplici e facili da usare. Ogni ricerca costa 3 crediti, acquistabili in crypto a 0.10 USD per credito.

Per iniziare

  1. o accedi al tuo account
  2. Ricarica i crediti con Bitcoin o Litecoin
  3. Cerca su internet tramite volto direttamente da codice

Esempi di codice per la ricerca tramite volto

  1. Upload - Invia un'immagine come multipart/form-data a /api/upload_pic e riceverai un id_search
  2. Ricerca - Manda l'id_search a /api/search per avviare la ricerca e seguirne l'avanzamento
  3. Risultati - Scorri i risultati in JSON

La documentazione completa degli endpoint e delle strutture dati la trovi nella Specifica Swagger di FaceCheck.

Modalità test

Il codice di esempio ha TESTING_MODE=True di default. In modalità test vengono scansionati solo 100.000 volti. Le ricerche girano veloci, non consumano risorse e non scalano crediti, ma i risultati non avranno senso.

Quando sei pronto per andare in produzione, imposta TESTING_MODE=False.

import time
import requests
import urllib.request
TESTING_MODE = True
APITOKEN = 'YOUR_API_TOKEN' # Your API Token

# Download the photo of the person you want to find
urllib.request.urlretrieve('https://www.indiewire.com/wp-content/uploads/2018/01/daniel-craig.jpg?w=300', "daniel.jpg")
image_file = 'daniel.jpg' 

def search_by_face(image_file):
    if TESTING_MODE:
        print('****** TESTING MODE search, results are inacurate, and queue wait is long, but credits are NOT deducted ******')

    site='https://facecheck.id'
    headers = {'accept': 'application/json', 'Authorization': APITOKEN}
    files = {'images': open(image_file, 'rb'), 'id_search': None}
    response = requests.post(site+'/api/upload_pic', headers=headers, files=files).json()

    if response['error']:
        return f"{response['error']} ({response['code']})", None

    id_search = response['id_search']
    print(response['message'] + ' id_search='+id_search)
    json_data = {'id_search': id_search, 'with_progress': True, 'status_only': False, 'demo': TESTING_MODE}

    while True:
        response = requests.post(site+'/api/search', headers=headers, json=json_data).json()
        if response['error']:
            return f"{response['error']} ({response['code']})", None
        if response['output']:
            return None, response['output']['items']
        print(f'{response["message"]} progress: {response["progress"]}%')
        time.sleep(1)


# Search the Internet by face
error, urls_images = search_by_face(image_file)

if urls_images:
    for im in urls_images:      # Iterate search results
        score = im['score']     # 0 to 100 score how well the face is matching found image
        url = im['url']         # url to webpage where the person was found
        image_base64 = im['base64']     # thumbnail image encoded as base64 string
        print(f"{score} {url} {image_base64[:32]}...")
else:
    print(error)
using System.Net;

namespace FaceCheckAPI
{
    public class SearchItem
    {
        public string? guid { get; set; }
        public int score { get; set; }
        public string? base64 { get; set; }
        public string? url { get;  set; }
        public int index { get; set; } = -1;
    }

    public class Search_Results
    {
        public List<SearchItem>? items { get; set; }
    }

    public class InputImage
    {
        public string? base64 { get; set; }
        public string? id_pic { get; set; }
    }

    public class BrowserJsonResponse
    {
        public string? id_search { get; set; }
        public string? message { get; set; }
        public int? progress { get; set; }
        public string? error { get; set; }
        public string? code { get; set; }
        public Search_Results? output { get; set; }
        public List<InputImage>? input { get; set; }
    }

    public class FaceCheckAPI
    {
        static bool TESTING_MODE = true;
        static string APITOKEN = "YOUR_API_TOKEN"; // Your API Token
        static string site = "https://facecheck.id";

        static readonly HttpClient client = new HttpClient();
        static FaceCheckAPI()
        {
            client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", APITOKEN);
        }
        public static async Task<List<SearchItem>?> Search_by_FaceAsync(string image_file)
        {
            if (TESTING_MODE) Console.WriteLine("****** TESTING MODE search, results are inaccurate, and queue wait is long, but credits are NOT deducted ******");
            using var content = new MultipartFormDataContent("Upload----" + DateTime.Now.Ticks.ToString("x"));
            using var ImageStream = new FileStream(image_file, FileMode.Open, FileAccess.Read, FileShare.None);
            content.Add(new StreamContent(ImageStream), "images", Path.GetFileName(image_file));
            using var message = await client.PostAsync(site + "/api/upload_pic", content);
            var input = await message.Content.ReadAsStringAsync();
            BrowserJsonResponse? a = System.Text.Json.JsonSerializer.Deserialize<BrowserJsonResponse?>(input);
            if (a.error != null) throw new Exception(a.error);
            Console.WriteLine(a.message + " id_search=" + a.id_search);

            while (true)
            {
                BrowserJsonResponse? b = await PostSearch(Convert.ToString(a.id_search));
                if (b.error != null) throw new Exception(b.error);
                if (b.output != null) return b.output.items;
                Console.WriteLine($"{b.message} Progress: {b.progress}%");
                await Task.Delay(1000);
            }

        }
            
        

        private static async Task<BrowserJsonResponse?> PostSearch(string? id_search)
        {
            using var _Body = new StringContent($"{{\"id_search\":\"{id_search}\",\"with_progress\":true,\"status_only\":false,\"demo\":{(TESTING_MODE ? "true" : "false")}}}");
            _Body.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
            using var msg = await client.PostAsync(site + "/api/search", _Body);
            string json = await msg.Content.ReadAsStringAsync();
            return Utf8Json.JsonSerializer.Deserialize<BrowserJsonResponse>(json);
        }

    }

    internal class Program
    {
        static async Task Main(string[] args)
        {
            try
            {
                //download a test image 
                using (WebClient webClient = new WebClient())
                    webClient.DownloadFile("https://www.indiewire.com/wp-content/uploads/2018/01/daniel-craig.jpg?w=300", "daniel.jpg");
                

                //Search the Internet by face
                var images = await FaceCheckAPI.Search_by_FaceAsync("daniel.jpg");
                if (images != null)
                    foreach (SearchItem im in images) //Iterate search results
                    {
                        var score = im.score;     // 0 to 100 score how well the face is matching found image
                        var url = im.url;         // url to webpage where the person was found
                        var image_base64 = im.base64;     // thumbnail image encoded as base64 string
                        //convert to binary .WEBP image
                        byte[] webp_image = Convert.FromBase64String(image_base64.Substring(image_base64.IndexOf(' ') + 1));
                        Console.WriteLine($"{score} {url} {image_base64?.Substring(0, 32)}...");
                    }
            }
            catch (Exception ex)
            {
                Console.WriteLine("ERROR: " + ex.Message);
            }
            Console.ReadKey();
        }
    }
}
const axios = require('axios');
const FormData = require('form-data');
const fs = require('fs');
const https = require('https');


const TESTING_MODE = true;
const APITOKEN = 'YOUR_API_TOKEN';


const downloadImage = (url, filename) => {
  return new Promise((resolve, reject) => {
    const file = fs.createWriteStream(filename);
    https.get(url, response => {
      response.pipe(file);
      file.on('finish', () => {
        file.close(resolve);
      });
      file.on('error', reject);
    });
  });
};


const search_by_face = async (image_file) => {
    if (TESTING_MODE) {
        console.log('****** TESTING MODE search, results are inacurate, and queue wait is long, but credits are NOT deducted ******');
    }


    const site = 'https://facecheck.id';
    const headers = {
        accept: 'application/json',
        Authorization: APITOKEN,
    };


    let form = new FormData();
    form.append('images', fs.createReadStream(image_file));
    form.append('id_search', '');


    let response = await axios.post(site+'/api/upload_pic', form, { headers: {
        ...form.getHeaders(),
        'accept': 'application/json',
        'Authorization': APITOKEN
    } });
    response = response.data;


    if (response.error) {
        return [`${response.error} (${response.code})`, null];
    }


    const id_search = response.id_search;
    console.log(`${response.message} id_search=${id_search}`);
    const json_data = {
        id_search: id_search,
        with_progress: true,
        status_only: false,
        demo: TESTING_MODE,
    };


    while (true) {
        response = await axios.post(site+'/api/search', json_data, { headers: headers });
        response = response.data;
        if (response.error) {
            return [`${response.error} (${response.code})`, null];
        }
        if (response.output) {
            return [null, response.output.items];
        }
        console.log(`${response.message} progress: ${response.progress}%`);
        await new Promise(r => setTimeout(r, 1000));
    }
};


const run = async () => {
    await downloadImage('https://www.indiewire.com/wp-content/uploads/2018/01/daniel-craig.jpg?w=300', 'daniel.jpg');

    // Search the Internet by face
    const [error, urls_images] = await search_by_face('daniel.jpg');


  if (urls_images) {
    urls_images.forEach(im => {
        const score = im.score;     // 0 to 100 score how well the face is matching found image
        const url = im.url;         // url to webpage where the person was found
        const image_base64 = im.base64;     // thumbnail image encoded as base64 string
        console.log(`${score} ${url} ${image_base64.slice(0, 32)}...`);
    });
  } else {
    console.log(error);
  }
}


run().catch(console.error);



const TESTING_MODE = true;
const APITOKEN = 'YOUR_API_TOKEN';

async function downloadTestImage(url: string, filepath: string): Promise<void> {
    const fs = await import('fs');
    const response = await fetch(url);
    const buffer = await response.arrayBuffer();
    fs.writeFileSync(filepath, Buffer.from(buffer));
}

async function searchByFace(imageFile: string) {
    if (TESTING_MODE) {
        console.log('****** TESTING MODE - results are inaccurate, queue is slow, but no credits deducted ******');
    }

    const fs = await import('fs');
    const site = 'https://facecheck.id';
    const headers = { 'Authorization': APITOKEN };

    // Upload image
    const formData = new FormData();
    const imageBuffer = fs.readFileSync(imageFile);
    const imageBlob = new Blob([imageBuffer]);
    formData.append('images', imageBlob, imageFile);

    const uploadRes = await fetch(`${site}/api/upload_pic`, {
        method: 'POST',
        headers,
        body: formData
    });
    const uploadData = await uploadRes.json();

    if (uploadData.error) {
        throw new Error(`${uploadData.error} (${uploadData.code})`);
    }

    const idSearch = uploadData.id_search;
    console.log(`${uploadData.message} id_search=${idSearch}`);

    // Poll for results
    const searchPayload = {
        id_search: idSearch,
        with_progress: true,
        status_only: false,
        demo: TESTING_MODE
    };

    while (true) {
        const searchRes = await fetch(`${site}/api/search`, {
            method: 'POST',
            headers: { ...headers, 'Content-Type': 'application/json' },
            body: JSON.stringify(searchPayload)
        });
        const searchData = await searchRes.json();

        if (searchData.error) {
            throw new Error(`${searchData.error} (${searchData.code})`);
        }

        if (searchData.output) {
            return searchData.output.items;
        }

        console.log(`${searchData.message} progress: ${searchData.progress}%`);
        await new Promise(resolve => setTimeout(resolve, 1000));
    }
}

// Main
(async () => {
    await downloadTestImage(
        'https://www.indiewire.com/wp-content/uploads/2018/01/daniel-craig.jpg?w=300',
        'daniel.jpg'
    );

    try {
        const results = await searchByFace('daniel.jpg');
        for (const item of results) {
            console.log(`${item.score} ${item.url} ${item.base64.substring(0, 32)}...`);
        }
    } catch (error) {
        console.error(error instanceof Error ? error.message : String(error));
    }
})();
import org.json.JSONArray;
import org.json.JSONObject;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.NoRouteToHostException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;

public class API_TEST {
    private static final boolean TESTING_MODE = true;
    private static final String APITOKEN = "YOUR_API_TOKEN";
    private static final String IMAGE_URL = "https://www.indiewire.com/wp-content/uploads/2018/01/daniel-craig.jpg?w=300";

    public static void main(String[] args) {
        try {
            String imageFilePath = downloadImage();
            JSONArray urlsImages;

            if (TESTING_MODE) {
                System.out.println("****** TESTING MODE search, results are bad, and queue wait is long, but credits are NOT deducted ******");
            }

            String site = "https://facecheck.id";
            String authToken = APITOKEN;

            // Upload the image
            JSONObject uploadResponse = uploadImage(site, authToken, imageFilePath);
            // System.out.println(uploadResponse);
            if (uploadResponse.has("error") && !uploadResponse.isNull("error")) {
                System.out.println("Error Code: " + uploadResponse.getString("code") + " , " + uploadResponse.getString("error"));
                return;
            }

            String idSearch = uploadResponse.getString("id_search");
            System.out.println(uploadResponse.getString("message") + " id_search=" + idSearch);

            JSONObject jsonData = new JSONObject()
                    .put("id_search", idSearch)
                    .put("with_progress", true)
                    .put("status_only", false)
                    .put("demo", TESTING_MODE);

            while (true) {
                JSONObject searchResponse = searchImage(site, authToken, jsonData);
                if (searchResponse.has("error") && !searchResponse.isNull("error")) {
                    System.out.println("Error Code: " + searchResponse.getString("code") + " , " + searchResponse.getString("error"));
                    return;
                }

                if (searchResponse.has("output") && !searchResponse.isNull("output")) {
                    urlsImages = searchResponse.getJSONObject("output").getJSONArray("items");
                    break;
                }

                System.out.println(searchResponse.getString("message") + " progress: " + searchResponse.getInt("progress") + "%");
                Thread.sleep(1000);
            }

            if (urlsImages != null) {
                for (int i = 0; i < urlsImages.length(); i++) {
                    JSONObject im = urlsImages.getJSONObject(i);
                    int score = im.getInt("score");
                    String url = im.getString("url");
                    String imageBase64 = im.getString("base64");

                    System.out.println(score + " " + url + " " + imageBase64.substring(0, 32) + "...");
                }
            }
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static String getImageExtensionFromURL(String imageUrl) throws MalformedURLException {
        try {
            URL url = new URL(imageUrl);
            String path = url.getPath();
            String fileName = path.substring(path.lastIndexOf('/') + 1);
            return fileName.substring(fileName.lastIndexOf('.') + 1);
        } catch (Exception exception) {
            System.out.println(exception.getMessage());
            throw exception;
        }
    }

    private static String downloadImage() throws IOException {
        String imageFileName = "SearchImage." + getImageExtensionFromURL(IMAGE_URL) ;
        URL imageUrl = new URL(IMAGE_URL);
        try (InputStream in = imageUrl.openStream()) {
            Files.copy(in, Paths.get(imageFileName), StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException exception) {
            System.out.println(exception.getMessage());
            throw exception;
        }
        return imageFileName;
    }

    private static JSONObject uploadImage(String site, String authToken, String imageFilePath) throws IOException {
        String boundary = "*****" + Long.toHexString(System.currentTimeMillis()) + "*****";
        String lineEnd = "\r\n";
        String twoHyphens = "--";

        URL url = new URL(site + "/api/upload_pic");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setDoOutput(true);
        connection.setRequestMethod("POST");
        connection.setRequestProperty("accept", "application/json");
        connection.setRequestProperty("Authorization", authToken);
        connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);

        try (DataOutputStream dos = new DataOutputStream(connection.getOutputStream())) {
            dos.writeBytes(twoHyphens + boundary + lineEnd);
            dos.writeBytes("Content-Disposition: form-data; name=\"images\";filename=\"" + imageFilePath + "\"" + lineEnd);
            dos.writeBytes(lineEnd);

            try (FileInputStream fis = new FileInputStream(imageFilePath)) {
                byte[] buffer = new byte[1024];
                int bytesRead;
                while ((bytesRead = fis.read(buffer)) != -1) {
                    dos.write(buffer, 0, bytesRead);
                }
            }

            dos.writeBytes(lineEnd);
            dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
            dos.flush();
        }

        try (InputStream is = connection.getInputStream();
             BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
            StringBuilder response = new StringBuilder();
            String line;
            while ((line = br.readLine()) != null) {
                response.append(line);
            }
            return new JSONObject(response.toString());
        }
    }

    private static JSONObject searchImage(String site, String authToken, JSONObject jsonData) throws IOException {
        URL url = new URL(site + "/api/search");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setDoOutput(true);
        connection.setRequestMethod("POST");
        connection.setRequestProperty("accept", "application/json");
        connection.setRequestProperty("Authorization", authToken);
        connection.setRequestProperty("Content-Type", "application/json");

        try (DataOutputStream dos = new DataOutputStream(connection.getOutputStream())) {
            dos.writeBytes(jsonData.toString());
            dos.flush();
        }  catch (Exception exception) {
            System.out.println(exception.getMessage());
            throw exception;
        }

        try (InputStream is = connection.getInputStream();
             BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
            StringBuilder response = new StringBuilder();
            String line;
            while ((line = br.readLine()) != null) {
                response.append(line);
            }
            return new JSONObject(response.toString());
        } catch (NoRouteToHostException exception) {
            System.out.println(exception.getMessage());
            throw exception;
        }
    }


}
//#define CURL_STATICLIB
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <thread>
#include "curl/curl.h"
#include "json/json.h"

using namespace std;

const bool TESTING_MODE = true;
const std::string APITOKEN = "YOUR_API_TOKEN";
const std::string IMAGE_URL = "https://www.indiewire.com/wp-content/uploads/2018/01/daniel-craig.jpg?w=300";

std::string getImageExtensionFromURL(const std::string& url) {
    // Find the last occurrence of '.' in the URL
    size_t dotPos = url.find_last_of('.');

    if (dotPos == std::string::npos) {
        // No extension found
        return "";
    }

    // Find the first occurrence of '?' after the last dot position
    size_t queryParamPos = url.find_first_of('?', dotPos);

    // Extract the extension from the URL
    std::string extension;
    if (queryParamPos != std::string::npos) {
        extension = url.substr(dotPos + 1, queryParamPos - dotPos - 1);
    } else {
        extension = url.substr(dotPos + 1);
    }

    return "jpg";
}

std::string downloadImage() {
    std::string imageFileName = "SearchImage." + getImageExtensionFromURL(IMAGE_URL);
    cout << "MESSAGE: Downloading Image..." << endl;
    CURL* curl = curl_easy_init();
    if (!curl) {
        std::cout << "Error: Failed to initialize CURL." << std::endl;
        exit(EXIT_FAILURE);
    }

    
    FILE* imageFile;
#ifdef _WIN32
    fopen_s(&imageFile, imageFileName.c_str(), "wb");
#else
    imageFile = fopen(imageFileName.c_str(), "wb");
#endif
    if (!imageFile) {
        std::cout << "Error: Failed to create image file." << std::endl;
        curl_easy_cleanup(curl);
        exit(EXIT_FAILURE);
    }

    curl_easy_setopt(curl, CURLOPT_URL, IMAGE_URL.c_str());
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, imageFile);
    curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);

    CURLcode res = curl_easy_perform(curl);
    curl_easy_cleanup(curl);
    fclose(imageFile);

    if (res != CURLE_OK) {
        std::cout << "Error: Failed to download image." << std::endl;
        exit(EXIT_FAILURE);
    }

    return imageFileName;
}

size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* output) {
    size_t totalSize = size * nmemb;
    output->append(static_cast<char*>(contents), totalSize);
    return totalSize;
}

Json::Value uploadImage(const std::string& site, const std::string& authToken, const std::string& imageFilePath) {
    std::string boundary = "*****" + std::to_string(std::time(nullptr)) + "*****";

    std::string url = site + "/api/upload_pic";
    CURL* curl = curl_easy_init();
    if (!curl) {
        std::cout << "Error: Failed to initialize CURL." << std::endl;
        exit(EXIT_FAILURE);
    }

    struct curl_slist* headers = nullptr;
    headers = curl_slist_append(headers, ("Authorization: " + authToken).c_str());
    headers = curl_slist_append(headers, "accept: application/json");

    std::string responseString; // To store the response data
    curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
    curl_easy_setopt(curl, CURLOPT_POST, 1L);
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);

    // Create the form data
    curl_mime* form = curl_mime_init(curl);
    curl_mimepart* part = curl_mime_addpart(form);
    curl_mime_name(part, "images");
    curl_mime_filedata(part, imageFilePath.c_str());

    // Attach the form data to the request
    curl_easy_setopt(curl, CURLOPT_MIMEPOST, form);

    // Set the write callback function
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
    // Set the pointer to responseString as the user data to pass to the callback function
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &responseString);
    curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L);
    CURLcode res = curl_easy_perform(curl);
    curl_slist_free_all(headers);
    curl_mime_free(form);
    curl_easy_cleanup(curl);

    if (res != CURLE_OK) {
        std::cout << "Error: Failed to upload image." << std::endl;
        exit(EXIT_FAILURE);
    }

    Json::Value response;
    Json::CharReaderBuilder reader;
    std::string errors;
    std::istringstream iss(responseString);
    if (!Json::parseFromStream(reader, iss, &response, &errors)) {
        std::cout << "Error: Failed to parse JSON response." << std::endl;
        exit(EXIT_FAILURE);
    }
    return response;
}

Json::Value searchImage(const std::string& site, const std::string& authToken, const Json::Value& jsonData) {
    std::string url = site + "/api/search";
    CURL* curl = curl_easy_init();
    if (!curl) {
        std::cout << "Error: Failed to initialize CURL." << std::endl;
        exit(EXIT_FAILURE);
    }

    struct curl_slist* headers = nullptr;
    headers = curl_slist_append(headers, ("Authorization: " + authToken).c_str());
    headers = curl_slist_append(headers, "accept: application/json");
    headers = curl_slist_append(headers, "Content-Type: application/json");
    string responseString;
    std::string jsonDataStr = jsonData.toStyledString();
    curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
    curl_easy_setopt(curl, CURLOPT_POST, 1L);
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, jsonDataStr.c_str());
    curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
    curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L);
    //curl_easy_setopt(curl, CURLOPT_WRITEDATA, stdout);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
    // Set the pointer to responseString as the user data to pass to the callback function
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &responseString);

    // Set the option to suppress the output
    curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L);
    CURLcode res = curl_easy_perform(curl);
    curl_slist_free_all(headers);
    curl_easy_cleanup(curl);

    if (res != CURLE_OK) {
        std::cout << "Error: Failed to perform search." << std::endl;
        exit(EXIT_FAILURE);
    }

    Json::Value response;
    Json::CharReaderBuilder reader;
    std::string errors;
    std::istringstream iss(responseString);
    if (!Json::parseFromStream(reader, iss, &response, &errors)) {
        std::cout << "Error: Failed to parse JSON response." << std::endl;
        exit(EXIT_FAILURE);
    }
    return response;
}

int main() {
    try {
        std::string imageFilePath = downloadImage();
        Json::Value urlsImages;

        if (TESTING_MODE) {
            std::cout << "****** TESTING MODE search, results are bad, but credits are NOT deducted ******" << std::endl;
        }

        std::string site = "https://facecheck.id";
        std::string authToken = APITOKEN;

        // Upload the image
        Json::Value uploadResponse = uploadImage(site, authToken, imageFilePath);
        if(uploadResponse.isMember("error")) {
            if (uploadResponse.isMember("error") && !uploadResponse["error"].isNull()) {
                std::cout << "Error Code: " << uploadResponse["code"].asString() << " , " << uploadResponse["error"].asString() << std::endl;
                return 1;
            }
        }

        std::string idSearch = uploadResponse["id_search"].asString();
        std::cout << uploadResponse["message"].asString() << " id_search=" << idSearch << std::endl;

        Json::Value jsonData;
        jsonData["id_search"] = idSearch;
        jsonData["with_progress"] = true;
        jsonData["status_only"] = false;
        jsonData["demo"] = TESTING_MODE;

        while (true) {
            Json::Value searchResponse = searchImage(site, authToken, jsonData);
            if (searchResponse.isMember("error") && !searchResponse["error"].isNull()) {
                std::cout << "Error Code: " << searchResponse["code"].asString() << " , " << searchResponse["error"].asString() << std::endl;
                return 1;
            }

            if (searchResponse.isMember("output") && !searchResponse["output"].isNull()) {
                urlsImages = searchResponse["output"]["items"];
                break;
            }

            std::cout<< searchResponse["message"].asString() << " progress: " << searchResponse["progress"] << "%" << std::endl;
            std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        }

        cout << "MESSAGE: Image Search Completed!" << endl;
        if (!urlsImages.isNull()) {
            for (unsigned int i = 0; i < urlsImages.size(); ++i) {
                Json::Value im = urlsImages[i];
                int score = im["score"].asInt();
                std::string url = im["url"].asString();
                std::string imageBase64 = im["base64"].asString();

                std::cout << score << " " << url << " " << imageBase64.substr(0, 32) << "..." << std::endl;
            }
        }
    }
    catch (const std::exception& e) {
        std::cout << "Exception: " << e.what() << std::endl;
        return 1;
    }

    return 0;
}
import org.json.JSONArray
import org.json.JSONObject
import java.io.*
import java.net.HttpURLConnection
import java.net.MalformedURLException
import java.net.URL
import java.nio.file.Files
import java.nio.file.Paths
import java.nio.file.StandardCopyOption

object FaceCheck {
    private const val TESTING_MODE = true
    private const val APITOKEN = "YOUR_API_TOKEN" // Your API Token
    private const val IMAGE_URL = "https://www.indiewire.com/wp-content/uploads/2018/01/daniel-craig.jpg?w=300"

    @JvmStatic
    fun main(args: Array<String>) {
        try {
            val imageFilePath = downloadImage()
            val urlsImages: JSONArray?

            if (TESTING_MODE) {
                println("****** TESTING MODE search, results are bad, but credits are NOT deducted ******")
            }

            val site = "https://facecheck.id"
            val authToken = APITOKEN

            // Upload the image
            val uploadResponse = uploadImage(site, authToken, imageFilePath)
            if (uploadResponse.has("error") && !uploadResponse.isNull("error")) {
                println(
                    "Error Code: " + uploadResponse.getString("code") + " , " + uploadResponse.getString("error")
                )
                return
            }

            val idSearch = uploadResponse.getString("id_search")
            println(uploadResponse.getString("message") + " id_search=$idSearch")

            val jsonData = JSONObject()
                .put("id_search", idSearch)
                .put("with_progress", true)
                .put("status_only", false)
                .put("demo", TESTING_MODE)

            while (true) {
                val searchResponse = searchImage(site, authToken, jsonData)
                if (searchResponse.has("error") && !searchResponse.isNull("error")) {
                    println(
                        "Error Code: " + searchResponse.getString("code") + " , " + searchResponse.getString("error")
                    )
                    return
                }

                if (searchResponse.has("output") && !searchResponse.isNull("output")) {
                    urlsImages = searchResponse.getJSONObject("output").getJSONArray("items")
                    break
                }

                println(
                    searchResponse.getString("message") + " progress: " + searchResponse.getInt("progress") + "%"
                )
                Thread.sleep(1000)
            }

            if (urlsImages != null) {
                for (i in 0 until urlsImages.length()) {
                    val im = urlsImages.getJSONObject(i)
                    val score = im.getInt("score")
                    val url = im.getString("url")
                    val imageBase64 = im.getString("base64")

                    println("$score $url ${imageBase64.substring(0, 32)}...")
                }
            }
        } catch (e: IOException) {
            e.printStackTrace()
        } catch (e: InterruptedException) {
            e.printStackTrace()
        }
    }

    @Throws(IOException::class)
    private fun downloadImage(): String {
        val imageFileName = "SearchImage.${getImageExtensionFromURL(IMAGE_URL)}"
        val imageUrl = URL(IMAGE_URL)
        imageUrl.openStream().use { `in` ->
            Files.copy(`in`, Paths.get(imageFileName), StandardCopyOption.REPLACE_EXISTING)
        }
        return imageFileName
    }

    @Throws(IOException::class)
    private fun uploadImage(site: String, authToken: String, imageFilePath: String): JSONObject {
        val boundary = "*****" + java.lang.Long.toHexString(System.currentTimeMillis()) + "*****"
        val lineEnd = "\r\n"
        val twoHyphens = "--"

        val url = URL("$site/api/upload_pic")
        val connection = url.openConnection() as HttpURLConnection
        connection.doOutput = true
        connection.requestMethod = "POST"
        connection.setRequestProperty("accept", "application/json")
        connection.setRequestProperty("Authorization", authToken)
        connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=$boundary")

        DataOutputStream(connection.outputStream).use { dos ->
            dos.writeBytes(twoHyphens + boundary + lineEnd)
            dos.writeBytes("Content-Disposition: form-data; name=\"images\";filename=\"$imageFilePath\"$lineEnd")
            dos.writeBytes(lineEnd)

            FileInputStream(imageFilePath).use { fis ->
                val buffer = ByteArray(1024)
                var bytesRead: Int
                while (fis.read(buffer).also { bytesRead = it } != -1) {
                    dos.write(buffer, 0, bytesRead)
                }
            }

            dos.writeBytes(lineEnd)
            dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd)
            dos.flush()
        }

        val response = StringBuilder()
        connection.inputStream.bufferedReader().use { br ->
            var line: String?
            while (br.readLine().also { line = it } != null) {
                response.append(line)
            }
        }
        return JSONObject(response.toString())
    }

    @Throws(IOException::class)
    private fun searchImage(site: String, authToken: String, jsonData: JSONObject): JSONObject {
        val url = URL("$site/api/search")
        val connection = url.openConnection() as HttpURLConnection
        connection.doOutput = true
        connection.requestMethod = "POST"
        connection.setRequestProperty("accept", "application/json")
        connection.setRequestProperty("Authorization", authToken)
        connection.setRequestProperty("Content-Type", "application/json")

        DataOutputStream(connection.outputStream).use { dos ->
            dos.writeBytes(jsonData.toString())
            dos.flush()
        }

        val response = StringBuilder()
        connection.inputStream.bufferedReader().use { br ->
            var line: String?
            while (br.readLine().also { line = it } != null) {
                response.append(line)
            }
        }

        return JSONObject(response.toString())
    }

    @Throws(MalformedURLException::class)
    fun getImageExtensionFromURL(imageUrl: String): String {
        try {
            val url = URL(imageUrl)
            val path = url.path
            val fileName = path.substring(path.lastIndexOf('/') + 1)
            return fileName.substring(fileName.lastIndexOf('.') + 1)
        } catch (exception: Exception) {
            // If any error occurs, return null or an appropriate default value
            println(exception.message)
            throw exception
        }
    }
}
use reqwest;
use serde::{Deserialize, Serialize};
use std::fs::File;
use std::io::Write;
use tokio;

const TESTING_MODE: bool = true;
const API_TOKEN: &str = "YOUR_API_TOKEN";

#[derive(Debug, Deserialize)]
struct UploadResponse {
    error: Option<String>,
    code: Option<String>,
    id_search: Option<String>,
    message: Option<String>,
}

#[derive(Debug, Deserialize)]
struct SearchResponse {
    error: Option<String>,
    code: Option<String>,
    message: Option<String>,
    progress: Option<u32>,
    output: Option<SearchOutput>,
}

#[derive(Debug, Deserialize)]
struct SearchOutput {
    items: Vec<SearchResult>,
}

#[derive(Debug, Deserialize)]
struct SearchResult {
    score: f64,
    url: String,
    base64: String,
}

#[derive(Debug, Serialize)]
struct SearchRequest {
    id_search: String,
    with_progress: bool,
    status_only: bool,
    demo: bool,
}

async fn download_file(url: &str, filename: &str) -> Result<(), Box<dyn std::error::Error>> {
    let response = reqwest::get(url).await?;
    let bytes = response.bytes().await?;
    
    let mut file = File::create(filename)?;
    file.write_all(&bytes.to_vec())?;
    
    Ok(())
}

async fn search_by_face(image_file: &str) -> Result<Vec<SearchResult>, Box<dyn std::error::Error>> {
    if TESTING_MODE {
        println!("****** TESTING MODE search, results are inaccurate, and queue wait is long, but credits are NOT deducted ******");
    }
    
    let site = "https://facecheck.id";
    let client = reqwest::Client::new();
    
    // Upload the image
    let file = tokio::fs::read(image_file).await?;
    let part = reqwest::multipart::Part::bytes(file)
        .file_name(image_file.to_string())
        .mime_str("image/jpeg")?;
    
    let form = reqwest::multipart::Form::new()
        .part("images", part);
    
    let upload_response: UploadResponse = client
        .post(format!("{}/api/upload_pic", site))
        .header("accept", "application/json")
        .header("Authorization", API_TOKEN)
        .multipart(form)
        .send()
        .await?
        .json()
        .await?;
    
    if let Some(error) = upload_response.error {
        return Err(format!("{} ({})", error, upload_response.code.unwrap_or_default()).into());
    }
    
    let id_search = upload_response.id_search
        .ok_or("No id_search in response")?;
    
    println!("{} id_search={}", upload_response.message.unwrap_or_default(), id_search);
    
    // Poll for results
    let search_request = SearchRequest {
        id_search: id_search.clone(),
        with_progress: true,
        status_only: false,
        demo: TESTING_MODE,
    };
    
    loop {
        let search_response: SearchResponse = client
            .post(format!("{}/api/search", site))
            .header("accept", "application/json")
            .header("Authorization", API_TOKEN)
            .json(&search_request)
            .send()
            .await?
            .json()
            .await?;
        
        if let Some(error) = search_response.error {
            return Err(format!("{} ({})", error, search_response.code.unwrap_or_default()).into());
        }
        
        if let Some(output) = search_response.output {
            return Ok(output.items);
        }
        
        println!(
            "{} progress: {}%",
            search_response.message.unwrap_or_default(),
            search_response.progress.unwrap_or(0)
        );
        
        tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
    }
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Download the photo
    let image_url = "https://www.indiewire.com/wp-content/uploads/2018/01/daniel-craig.jpg?w=300";
    let image_file = "daniel.jpg";
    
    download_file(image_url, image_file).await?;
    
    // Search the Internet by face
    match search_by_face(image_file).await {
        Ok(urls_images) => {
            for im in urls_images {
                let score = im.score;
                let url = im.url;
                let base64_preview = if im.base64.len() > 32 {
                    &im.base64[..32]
                } else {
                    &im.base64
                };
                println!("{} {} {}...", score, url, base64_preview);
            }
        }
        Err(error) => {
            println!("{}", error);
        }
    }
    
    Ok(())
}