diff --git a/plugins/tasks/Extractor.php b/plugins/tasks/Extractor.php
new file mode 100644
index 0000000000000000000000000000000000000000..1ad125ed5bfe514198182a28be13b2ad817882d4
--- /dev/null
+++ b/plugins/tasks/Extractor.php
@@ -0,0 +1,315 @@
+<?php
+
+class Extractor implements EndpointInterface
+{
+  private TaskGateway $gateway;
+
+  public function __construct(TaskGateway $gateway)
+  {
+    $this->gateway = $gateway;
+  }
+
+  /**
+   * @return array
+   * Part of the interface of orchestrator plugin to treat GET method
+   */
+  public function processEndPointGet(): array
+  {
+    // Retrieve tasks of type 'extract'
+    return $this->gateway->getObjectTypeTask('extract');
+  }
+
+  /**
+   * @param array|null $data
+   * @return array
+   * Note: Part of the interface of orchestrator plugin to treat POST method
+   */
+  public function processEndPointPost(array $data = NULL): array
+  {
+    return [];
+  }
+
+  /**
+   * @param array|null $data
+   * @return array
+   * Note: Part of the interface of orchestrator plugin to treat DELETE method
+   */
+  public function processEndPointDelete(array $data = NULL): array
+  {
+    return [];
+  }
+
+  /**
+   * @param array|null $data
+   * @return array
+   * @throws Exception
+   * Note: Part of the interface of orchestrator plugin to treat PATCH method
+   */
+  public function processEndPointPatch(array $data = NULL): array
+  {
+    $result = [];
+    $extractTasks = $this->gateway->getObjectTypeTask('extract');
+    
+    // Path is now expected in the JSON body ($data)
+    $path = $data['path'] ?? '/srv/orchestrator/';
+
+    foreach ($extractTasks as $task) {
+      try {
+        if (!$this->gateway->statusAndScheduleCheck($task)) {
+          // Skip this task if it does not meet the status and schedule criteria
+          continue;
+        }
+
+        // Get the main task configuration
+        $mainTaskConfig = $this->getExtractMainTaskConfig($task['fdtasksgranularmaster'][0]);
+        
+        // Get user DN from the task
+        $userDn = $task['fdtasksgranulardn'][0];
+        
+        // Get user attributes
+        $userAttributes = $this->getUserAttributes($userDn, $mainTaskConfig);
+        
+        // Format comes from the main task configuration
+        $format = isset($mainTaskConfig[0]['fdextractortaskformat']) ? 
+                 strtolower($mainTaskConfig[0]['fdextractortaskformat'][0]) : 'csv';
+        
+        // Create directory if it doesn't exist
+        $this->ensureDirectoryExists($path);
+        
+        // Get main task CN for filename
+        $mainTaskCn = $this->getMainTaskCn($task['fdtasksgranularmaster'][0]);
+        
+        // Determine filename with main task name and date with hours
+        $date = date('Y-m-d_H-i-s');
+        $filename = isset($data['filename']) ? 
+                   $path . $data['filename'] . '_' . $date . '.' . $format : 
+                   $path . $mainTaskCn . '_' . $date . '.' . $format;
+        
+        // Extract and write to file
+        $success = $this->extractToFile($userAttributes, $filename, $format);
+        
+        if ($success) {
+          $result[$task['dn']]['result'] = "User attributes successfully extracted to $filename";
+          $this->gateway->updateTaskStatus($task['dn'], $task['cn'][0], '2');
+        } else {
+          throw new Exception("Failed to write data to $filename");
+        }
+        
+      } catch (Exception $e) {
+        $result[$task['dn']]['result'] = "Error extracting user attributes: " . $e->getMessage();
+        $this->gateway->updateTaskStatus($task['dn'], $task['cn'][0], $e->getMessage());
+      }
+    }
+
+    return $result;
+  }
+
+  /**
+   * @param string $mainTaskDn
+   * @return array
+   * Note: Retrieve the configuration from the main extract task.
+   */
+  private function getExtractMainTaskConfig(string $mainTaskDn): array
+  {
+    return $this->gateway->getLdapTasks(
+      '(objectClass=fdExtractorTasks)',
+      ['fdExtractorTaskFormat', 'cn'],
+      '',
+      $mainTaskDn
+    );
+  }
+
+  /**
+   * @param string $userDn
+   * @param array $mainTaskConfig
+   * @return array
+   * Note: Get all user attributes from the user DN.
+   */
+  private function getUserAttributes(string $userDn, array $mainTaskConfig): array
+  {
+    // Get all user data from LDAP
+    $userData = $this->gateway->getLdapTasks(
+      '(objectClass=*)',
+      ['*'],
+      '',
+      $userDn
+    );
+    
+    // Process and return user data
+    $this->gateway->unsetCountKeys($userData);
+    return $userData;
+  }
+
+  /**
+   * @param string $path
+   * @return bool
+   * @throws Exception
+   * Note: Create directory if it doesn't exist.
+   */
+  private function ensureDirectoryExists(string $path): bool
+  {
+    if (!is_dir($path)) {
+      if (!mkdir($path, 0755, true)) {
+        throw new Exception("Failed to create directory: $path");
+      }
+    }
+    return true;
+  }
+
+  /**
+   * @param array $userAttributes
+   * @param string $filename
+   * @param string $format
+   * @return bool
+   * @throws Exception
+   * Note: Extract user attributes to a file.
+   */
+  private function extractToFile(array $userAttributes, string $filename, string $format): bool
+  {
+    switch (strtolower($format)) {
+      case 'csv':
+        return $this->exportToCsv($userAttributes, $filename);
+      case 'json':
+        return $this->exportToJson($userAttributes, $filename);
+      case 'xml':
+        return $this->exportToXml($userAttributes, $filename);
+      default:
+        return $this->exportToCsv($userAttributes, $filename);
+    }
+  }
+
+  /**
+   * @param array $userAttributes
+   * @param string $filename
+   * @return bool
+   * @throws Exception
+   * Note: Export user attributes to CSV.
+   */
+  private function exportToCsv(array $userAttributes, string $filename): bool
+  {
+    $fileExists = file_exists($filename);
+    $handle = fopen($filename, 'a');
+    
+    if ($handle === false) {
+      throw new Exception("Could not open file: $filename");
+    }
+    
+    try {
+      if (empty($userAttributes)) {
+        return true; // No attributes to write
+      }
+      
+      $user = $userAttributes[0];
+      $columns = [];
+      $data = [];
+      
+      // Prepare columns and data
+      foreach ($user as $attribute => $values) {
+        if (is_array($values)) {
+          foreach ($values as $key => $value) {
+            if (is_numeric($key)) {
+              $columns[] = $attribute;
+              $data[] = $value;
+              break; // Only take the first value for simplicity
+            }
+          }
+        }
+      }
+      
+      // Write header if file is new
+      if (!$fileExists) {
+        fputcsv($handle, $columns);
+      }
+      
+      // Write data
+      fputcsv($handle, $data);
+      
+      return true;
+    } finally {
+      fclose($handle);
+    }
+  }
+
+  /**
+   * @param array $userAttributes
+   * @param string $filename
+   * @return bool
+   * Note: Export user attributes to JSON.
+   */
+  private function exportToJson(array $userAttributes, string $filename): bool
+  {
+    $existingData = [];
+    
+    // Read existing data if file exists
+    if (file_exists($filename)) {
+      $existingJson = file_get_contents($filename);
+      if (!empty($existingJson)) {
+        $existingData = json_decode($existingJson, true) ?? [];
+      }
+    }
+    
+    // Add new data
+    $existingData[] = $userAttributes[0];
+    
+    // Write back to file
+    return file_put_contents($filename, json_encode($existingData, JSON_PRETTY_PRINT)) !== false;
+  }
+
+  /**
+   * @param array $userAttributes
+   * @param string $filename
+   * @return bool
+   * Note: Export user attributes to XML.
+   */
+  private function exportToXml(array $userAttributes, string $filename): bool
+  {
+    $dom = new DOMDocument('1.0', 'UTF-8');
+    $dom->formatOutput = true;
+    
+    // Create root element if file doesn't exist
+    if (file_exists($filename)) {
+      $dom->load($filename);
+      $root = $dom->documentElement;
+    } else {
+      $root = $dom->createElement('users');
+      $dom->appendChild($root);
+    }
+    
+    // Add new user element
+    $user = $dom->createElement('user');
+    
+    foreach ($userAttributes[0] as $attribute => $values) {
+      if (is_array($values)) {
+        foreach ($values as $key => $value) {
+          if (is_numeric($key)) {
+            $attr = $dom->createElement($attribute, htmlspecialchars($value));
+            $user->appendChild($attr);
+          }
+        }
+      }
+    }
+    
+    $root->appendChild($user);
+    
+    // Write to file
+    return $dom->save($filename) !== false;
+  }
+
+  /**
+   * Get the CN (Common Name) of the main task
+   * 
+   * @param string $mainTaskDn
+   * @return string
+   */
+  private function getMainTaskCn(string $mainTaskDn): string
+  {
+    $mainTask = $this->gateway->getLdapTasks(
+      '(objectClass=*)',
+      ['cn'],
+      '',
+      $mainTaskDn
+    );
+    
+    return $mainTask[0]['cn'][0] ?? 'extract';
+  }
+}
\ No newline at end of file