# How to process images from a local directory

A common use case for the [Image Editing API](/image-editing-api-plus-plan/quickstart-guide.md) or the [Remove Background API](/remove-background-api-basic-plan/quickstart-guide.md) is to process a large amount of images, which are stored in a local directory.

In this tutorial, we'll see how it's possible to process these images by integrating the [Image Editing API](/image-editing-api-plus-plan/quickstart-guide.md) or the [Remove Background API](/remove-background-api-basic-plan/quickstart-guide.md) with a Python script.

## Step 1: Calling the API

First, we'll write a function that can process a local image through the [Image Editing API](/image-editing-api-plus-plan/quickstart-guide.md) or the [Remove Background API](/remove-background-api-basic-plan/quickstart-guide.md) and save the result image returned by the API to the disk:

{% tabs %}
{% tab title="Code to integrate with the Image Editing API" %}

```python
import requests

API_KEY = "REPLACE_WITH_YOUR_API_KEY"

def process_image(input_image_path, output_image_path):
    try:
        url = "https://image-api.photoroom.com/v2/edit"

        with open(input_image_path, 'rb') as image_file:
            files = { "imageFile": image_file }

            headers = {
                "Accept": "image/png, application/json",
                "x-api-key": API_KEY
            }

            response = requests.post(url, files=files, headers=headers)
            response.raise_for_status()

            with open(output_image_path, 'wb') as f:
                f.write(response.content)
                print(f"Image downloaded and saved to {output_image_path}")

    except requests.RequestException as e:
        print(f"Error: {str(e)}")
        return str(e)
```

{% endtab %}

{% tab title="Code to integrate with the Remove Background API" %}

```python
import requests

API_KEY = "REPLACE_WITH_YOUR_API_KEY"

def process_image(input_image_path, output_image_path):
    try:
        url = "https://sdk.photoroom.com/v1/segment"

        with open(input_image_path, 'rb') as image_file:
            files = { "image_file": image_file }

            headers = {
                "Accept": "image/png, application/json",
                "x-api-key": API_KEY
            }

            response = requests.post(url, files=files, headers=headers)
            response.raise_for_status()

            with open(output_image_path, 'wb') as f:
                f.write(response.content)
                print(f"Image downloaded and saved to {output_image_path}")

    except requests.RequestException as e:
        print(f"Error: {str(e)}")
        return str(e)
```

{% endtab %}
{% endtabs %}

This code is pretty straightforward:

1. it opens the image stored at `input_image_path`
2. uses the `requests` library to make the POST HTTP call to the API
3. saves the result image at `output_image_path`

Notice that you will need to update the value of the constant `API_KEY` with your own API key.

{% hint style="info" %}
If you don't have an API key, here are the [steps to create yours](/getting-started/introduction.md#how-can-i-get-my-api-key).
{% endhint %}

## Step 2: Iterating over a local directory

Now that we have a function to process a single image, the next step is to iterate over all the images stored in a local directory and call `process_image()` for each of them.

```python
import concurrent.futures
import os

def iterate_over_directory(input_directory_path, result_directory_path):
    with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
        for root, _, files in os.walk(input_directory_path):
            for file in files:
                file_path = os.path.join(root, file)

                result_file_name = os.path.splitext(os.path.basename(file_path))[0] + '.png'
                result_path = os.path.join(result_directory_path, result_file_name)

                if not os.path.exists(result_path): # don't re-process images 
                    executor.submit(process_image, file_path, result_path)     
```

This time the code is a bit more complex, but here are its important steps:

1. we iterate over the files inside the directory at `input_directory_path`
2. then for each `file` we:&#x20;
   1. compose the `result_path` where the result image will be saved
   2. check that a file doesn't already exist at `result_path` (so as to not process the same image twice)
   3. call the function `process_image()` through an `executor`, which allows us to execute 4 API calls in parallel

{% hint style="info" %}
If you want, you can increase the value of the argument `max_workers` to run more API calls in parallel. Keep in mind though that the API is [rate limited to 60 calls/minutes](/getting-started/frequently-asked-questions.md#q-is-there-a-rate-limiting).
{% endhint %}

## Step 3: Running the script

We're almost there, the last thing we need is to actually run the script.

To do this we'll add this final piece of code:

```python
if __name__ == "__main__":
    INPUT_DIRECTORY = "./input/"
    OUTPUT_DIRECTORY = "./output/"

    if not os.path.exists(OUTPUT_DIRECTORY):
        os.makedirs(OUTPUT_DIRECTORY)

    iterate_over_directory(input_directory_path=INPUT_DIRECTORY, result_directory_path=OUTPUT_DIRECTORY)
```

Here we set the constants `INPUT_DIRECTORY` and `OUTPUT_DIRECTORY` to the paths of respectively:

* the directory where the input images are stored&#x20;
* the directory where we want to save the result images.

Then all that's left is to actually run the script using the terminal:

```bash
$ pip install requests # run once to install the library `requests`
$ python script.py
```

## Conclusion

In this tutorial, we saw how to use a Python script to easily process images stored locally with the Photoroom API.

## Download the code sample

Here's the entire code sample, if you want to easily save it to a file:

```python
import concurrent.futures
import os
import requests

API_KEY = "REPLACE_WITH_YOUR_API_KEY"

def process_image(input_image_path, output_image_path):
    try:
        url = "https://sdk.photoroom.com/v1/segment"

        with open(input_image_path, 'rb') as image_file:
            files = { "image_file": image_file }

            headers = {
                "Accept": "image/png, application/json",
                "x-api-key": API_KEY
            }

            response = requests.post(url, files=files, headers=headers)
            response.raise_for_status()

            with open(output_image_path, 'wb') as f:
                f.write(response.content)
                print(f"Image downloaded and saved to {output_image_path}")

    except requests.RequestException as e:
        print(f"Error: {str(e)}")
        return str(e)
    
def iterate_over_directory(input_directory_path, result_directory_path):
    with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
        for root, _, files in os.walk(input_directory_path):
            for file in files:
                file_path = os.path.join(root, file)

                result_file_name = os.path.splitext(os.path.basename(file_path))[0] + '.png'
                result_path = os.path.join(result_directory_path, result_file_name)

                if not os.path.exists(result_path): # don't re-process images 
                    executor.submit(process_image, file_path, result_path)    

if __name__ == "__main__":
    INPUT_DIRECTORY = "./input/"
    OUTPUT_DIRECTORY = "./output/"

    if not os.path.exists(OUTPUT_DIRECTORY):
        os.makedirs(OUTPUT_DIRECTORY)

    iterate_over_directory(input_directory_path=INPUT_DIRECTORY, result_directory_path=OUTPUT_DIRECTORY)
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.photoroom.com/integrations/how-to-process-images-from-a-local-directory.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
