diff --git a/webservice/request_darks.py b/webservice/request_darks.py
index 09b33283c82d55b39862e80c91a0f3165e060078..1cafba1a183fcaa0ef36cbc81ddad82dcbd5f360 100644
--- a/webservice/request_darks.py
+++ b/webservice/request_darks.py
@@ -11,6 +11,9 @@ parser.add_argument('--proposal', type=str,
 parser.add_argument('--instrument', type=str,
                     choices=["SPB", "MID", "FXE", "SCS", "DETLAB", "SQS", "HED"],
                     help='The instrument')
+parser.add_argument('--detectors', type=str, nargs='*',
+                    help='A list of detectors to process, default ["all"]',
+                    default=['all'])
 parser.add_argument('--cycle', type=str, help='The facility cycle')
 parser.add_argument('--run-high', type=str,
                     help='Run number of high gain data as an integer')
@@ -20,7 +23,8 @@ parser.add_argument('--run-low', type=str,
                     help='Run number of low gain data as an integer')
 parser.add_argument('--run', type=str, help='Run number as an integer')
 parser.add_argument('--reservation', type=str, help='Reservation to run on, default is to use configured reservations')  #noqa
-
+parser.add_argument('--bkg', action='store_true',
+                    help='Background mode: exit script after requesting dark.')
 
 args = vars(parser.parse_args())
 
@@ -31,7 +35,7 @@ con = socket.connect("tcp://max-exfl016:5555")
 uuid = str(datetime.now().timestamp().as_integer_ratio()[0])
 
 parm_list = ["dark", uuid, "SASEX", args["instrument"], args["cycle"],
-             args["proposal"]]
+             args["proposal"], ','.join(args["detectors"])]
 
 if "run_high" in args and args["run_high"]:
     parm_list += ["(\"run-high\", \"{}\")".format(args["run_high"])]
@@ -52,6 +56,8 @@ print(resp.decode())
 while True:
     socket.send("['query-rid', '{}']".format(uuid).encode())
     resp = socket.recv_multipart()[0]
+    if args["bkg"]:
+        break
     rl = resp.decode().split("\n")
     r = ["QUEUE" if "QUEUE" in r else r for r in rl]
     r = " | ".join(r)
diff --git a/webservice/serve_overview.py b/webservice/serve_overview.py
index 559c2f9c3eae6d616e41c1a2fc21abaaf76c25a9..1dcf1120df4753cdd16a99220c925a7361ac3396 100644
--- a/webservice/serve_overview.py
+++ b/webservice/serve_overview.py
@@ -40,6 +40,7 @@ class RequestHandler(BaseHTTPRequestHandler):
     def init_config(self):
 
         global config
+        global cal_config
 
         self.nodes_avail_res_cmd = config["shell-commands"]["nodes-avail-res"]
         self.total_jobs_cmd = config["shell-commands"]["total-jobs"]
@@ -92,7 +93,71 @@ class RequestHandler(BaseHTTPRequestHandler):
                 with open(fpath, "rb") as f:
                     self.wfile.write(f.read())
             return
+        if "update_form?" in self.path:
+            pars = self.path.split("?")[1].split("&")
+            pars = {x.split("=")[0]: x.split("=")[1] for x in pars}
+            if pars['instrument'] in ['Nothing', 'none']:
+                self.wfile.write(bytes("<br>", "utf8"))
+                return
+            host = config["server-config"]["host"]
+            port = config["server-config"]["port"]
+            if 'request_dark' in pars:
+                par_list = ['python', 'request_darks.py', '--bkg']
+                del pars["request_dark"]
+                for k, v in pars.items():
+                    par_list.append('--{}'.format(str(k).replace("_", "-")))
+                    if k == 'detectors':
+                        for det in v.split(","):
+                            par_list.append('{}'.format(det))
+                    elif k == 'proposal':
+                        par_list.append('{:06d}'.format(int(v)))
+                    else:
+                        par_list.append('{}'.format(v))
+
+                par_list = list(filter(None, par_list))
+                print('REQUEST DARK: ', par_list)
+                timeout = config["server-config"]["dark-timeout"]
+                try:
+                    msg = check_output(par_list, shell=False,
+                                       timeout=timeout).decode('utf8')
+                except Exception as e:
+                    msg = str(e)
+
+                self.wfile.write(bytes("<br>" + str(msg), "utf8"))
+                return
 
+            tmpl = Template(self.templates["checkbox"])
+            detectors = list(cal_config['dark'][pars['instrument']].keys())
+
+            det_list = []
+            if 'detectors' in pars:
+                det_list = pars['detectors'].split(",")
+
+            det_names = []
+            for d in detectors:
+                if d in det_list:
+                    det_names.append(["checked", d])
+                else:
+                    det_names.append(["", d])
+
+            run_names = []
+            run1_det = ["FASTCCD", "EPIX", "DSSC", "PNCCD"]
+            run3_det = ["LPD", "AGIPD", "JUNGFRAU"]
+            msg = ''
+            if any(y in x for x in det_list for y in run1_det):
+                run_names = ['run']
+            if any(y in x for x in det_list for y in run3_det):
+                if run_names == []:
+                    run_names = ['run_high', 'run_med', 'run_low']
+                else:
+                    run_names = []
+                    msg = "Incompatible choice"
+
+            message = tmpl.render(detectors=det_names, runs=run_names,
+                                  message=msg, host=host, port=port)
+
+            self.wfile.write(bytes(message, "utf8"))
+            return
         # Send headers
         self.send_header('Content-type', 'text/html')
         self.end_headers()
@@ -241,10 +306,15 @@ class RequestHandler(BaseHTTPRequestHandler):
         tmpl = self.templates["running-jobs"]
         running_jobs_r = Template(tmpl).render(running_jobs=running_jobs)
 
+        tmpl = self.templates["request-dark"]
+        request_dark_r = Template(tmpl).render(
+            instruments=cal_config['dark'].keys())
+
         tmpl = Template(self.templates["main-doc"])
         message = tmpl.render(maxwell_status=maxwell_status_r,
                               log_output=log_output_r,
                               last_characterizations=last_characterizations_r,
+                              request_dark=request_dark_r,
                               running_jobs=running_jobs_r)
         # Write content as utf-8 data
         self.wfile.write(bytes(message, "utf8"))
@@ -255,7 +325,10 @@ def run(configfile, port=8008):
     print('reading config file')
     with open(configfile, "r") as cf:
         global config
-        config = yaml.load(cf.read())
+        config = yaml.load(cf.read(), Loader=yaml.FullLoader)
+    with open(config["web-service"]["cal-config"], "r") as cf:
+        global cal_config
+        cal_config = yaml.load(cf.read(), Loader=yaml.FullLoader)
     print('starting server...')
     sconfig = config["server-config"]
     server_address = (sconfig["host"], sconfig["port"])
diff --git a/webservice/serve_overview.yaml b/webservice/serve_overview.yaml
index 7bd4f95bb8c2f357b11cd6a76a8785614220c581..fd2c4b49f88379d9f8a086bcdd030fffcd3f7c91 100644
--- a/webservice/serve_overview.yaml
+++ b/webservice/serve_overview.yaml
@@ -4,6 +4,8 @@ templates:
   log-output: ./templates/log_output.html
   last-characterizations: ./templates/last_characterizations.html
   running-jobs: ./templates/running_jobs.html
+  request-dark: ./templates/request_dark.html
+  checkbox: ./templates/checkbox.html
   css: ./templates/serve_overview.css
 
 shell-commands:
@@ -43,6 +45,8 @@ run-candidates:
 server-config:
     port: 8008
     host: max-exfl016
+    dark-timeout: 30
 
 web-service:
-    job-db: ./webservice_jobs.sqlite
\ No newline at end of file
+    job-db: ./webservice_jobs.sqlite
+    cal-config: /home/karnem/myscratch/calibration3/calibration_configurations/default.yaml
\ No newline at end of file
diff --git a/webservice/templates/checkbox.html b/webservice/templates/checkbox.html
new file mode 100644
index 0000000000000000000000000000000000000000..154128addd5ce626fed7589df1e37708469c963f
--- /dev/null
+++ b/webservice/templates/checkbox.html
@@ -0,0 +1,11 @@
+{% for checked, detector in  detectors %}
+    <input type="checkbox"  onchange="javascript:loadCheckbox();" id="detector{{loop.index}}"
+           name="detector" value="{{detector}}" {{checked}}> {{detector}}
+{% endfor %}
+
+<br>
+{{message}}
+{% for run_name in runs %}
+    <label >{{run_name}}:</label>
+    <input type="number" id="run{{loop.index}}" name="{{run_name}}" min="1" max="999999" size="4">
+{% endfor %}
\ No newline at end of file
diff --git a/webservice/templates/main_doc.html b/webservice/templates/main_doc.html
index 90bb6063bc4839192756b8c14e9f9385c7393df8..1a35e3a930a05a8fe6439b070fc4d5b2bc0c9def 100644
--- a/webservice/templates/main_doc.html
+++ b/webservice/templates/main_doc.html
@@ -7,7 +7,7 @@
 <body>
 {{ maxwell_status }}
 {{ running_jobs }}
-{{ last_characterizations }}
+{{ request_dark }}
 {{ log_output }}
 </body>
 </html>
diff --git a/webservice/templates/request_dark.html b/webservice/templates/request_dark.html
new file mode 100644
index 0000000000000000000000000000000000000000..c7dfefbaeca5f0e17c5561d7be3353bb739b7f18
--- /dev/null
+++ b/webservice/templates/request_dark.html
@@ -0,0 +1,116 @@
+<script>
+
+function loadCheckbox(command) {
+  var xhttp = new XMLHttpRequest();
+  xhttp.onreadystatechange = function() {
+    if (this.readyState == 4 && this.status == 200) {
+     document.getElementById("demo").innerHTML = this.responseText;
+    }
+  };
+
+  var cycle = document.getElementById("cycle").value;
+  var proposal = document.getElementById("proposal").value;
+
+  var element = document.getElementById("detector1");
+  var counter = 1
+  var det_list = ""
+  while (typeof(element) != 'undefined' && element != null) {
+    if(element.checked == true){
+      det_list += element.value + ","
+    }
+    counter++;
+    element = document.getElementById("detector"+counter);
+  }
+
+  var run_element = []
+  run_element[0] = document.getElementById("run1");
+  counter = 1
+  var run_list = ""
+  while (typeof(run_element[counter-1]) != 'undefined' && run_element[counter-1] != null) {
+    run_list += "&" + run_element[counter-1].name + "=" + run_element[counter-1].value
+    counter++;
+    run_element[counter-1] = document.getElementById("run"+counter);
+  }
+
+  var e = document.getElementById("instruments");
+  var msg = "instrument="+e.options[e.selectedIndex].value;
+
+  msg += "&cycle="+cycle
+  msg += "&proposal="+proposal
+  msg += "&detectors="+det_list
+  msg += run_list
+  if (command=='request'){
+    if (!isInt(cycle) || cycle.length!=6){
+      document.getElementById("msg_err").innerHTML = 'Cycle is not defined'
+      return
+    }
+    if (!isInt(proposal) || proposal.length<4 || proposal.length>6){
+      document.getElementById("msg_err").innerHTML = 'Proposal is not defined'
+      return
+    }
+    if (e.options[e.selectedIndex].value == 'none'){
+      document.getElementById("msg_err").innerHTML = 'Instrument is not defined'
+      return
+    }
+    if (det_list==''){
+      document.getElementById("msg_err").innerHTML = 'Detector is not defined'
+      return
+    }
+    for(i=0; i<counter-1; i++){
+      if(!isInt(run_element[i].value) || run_element[i].value.length>4 ){
+        document.getElementById("msg_err").innerHTML = run_element[i].name + ' is not defined'
+        return
+      }
+      for(j=i+1; j<counter-1; j++){
+        if( run_element[i].value == run_element[j].value ){
+          err_msg = run_element[i].name + ' and ' + run_element[j].name + ' are the same.'
+          document.getElementById("msg_err").innerHTML = err_msg
+          return
+        }
+      }
+    }
+    msg += "&request_dark=1"
+    document.getElementById("msg_err").innerHTML = ' <br>'
+    e.value = "none"
+    document.getElementById("demo").innerHTML = 'Requesting dark...'
+  }
+
+  xhttp.open("GET", "{{host}}:{{port}}/update_form?"+msg, true);
+  xhttp.send();
+}
+
+function isInt(value) {
+  return !isNaN(value) &&
+         parseInt(Number(value)) == value &&
+         !isNaN(parseInt(value, 10));
+}
+</script>
+
+<script type="text/javascript">
+window.addEventListener("load",function(){
+    document.getElementById("instruments").value="none";
+},false);
+</script>
+
+<div class="block">
+   <h2>Request dark</h2>
+
+    <form action="" target="result" method="get">
+        <label >cycle:</label>
+        <input type="number" id="cycle" name="cycle" min="100000" max="999999" size="6">
+        <label >proposal:</label>
+        <input type="number" id="proposal" name="proposal" min="1000" max="999999" size="6">
+        <select id="instruments" onChange="javascript:loadCheckbox();" >
+            <option value ="none" selected="selected" >Nothing</option>
+            {% for instrument in instruments %}
+                <option value ="{{instrument}}"> {{instrument}} </option>
+            {% endfor %}
+        </select>
+        <div id="demo">
+        </div>
+        <p><input type="button" value="request" onclick="javascript:loadCheckbox('request');" ></p>
+        <div id="msg_err"  style="color:red;font-weight:bold;font-size:160%;" >
+        </div>
+    </form>
+
+</div>
diff --git a/webservice/webservice.py b/webservice/webservice.py
index 51e60a32a64258b696d368a733988ce1ff13e097..d9676fce9136886feec6dde03b187d86aba34f7b 100644
--- a/webservice/webservice.py
+++ b/webservice/webservice.py
@@ -475,8 +475,13 @@ async def server_runner(config, mode):
                     runnr = runnr.replace("r", "")
                     wait_runs = [runnr]
                 if action == 'dark':
-                    rid, sase, instrument, cycle, proposal = payload[:5]
-                    runs = payload[5:]  # can be many
+                    (rid, sase, instrument, cycle, proposal,
+                     det_list) = payload[:6]
+                    msg = "Dark characterization for {} at {} is requested. " \
+                          "Checking files..."
+                    logging.info(msg.format(det_list, instrument))
+                    det_list = det_list.split(',')
+                    runs = payload[6:]  # can be many
                     for i, run in enumerate(runs):
                         erun = eval(run)
                         if isinstance(erun, (list, tuple)):
@@ -581,14 +586,15 @@ async def server_runner(config, mode):
                     for detector, dconfig in pconf[instrument].items():
                         # check if we find files according
                         # to mapping in raw run folder
+                        if detector not in det_list and det_list[0]!='all':
+                            continue
                         fl = glob.glob(
                             "{}/RAW-*{}*.h5".format(rpath, dconfig["inset"]))
                         if len(fl):
                             thisconf = copy.copy(dconfig)
-                            out_folder = '_'.join((out_folder,
-                                                   dconfig["inset"]))
                             thisconf["in-folder"] = in_folder
-                            thisconf["out-folder"] = out_folder
+                            thisconf["out-folder"] = '/'.join((out_folder,
+                                                   detector.replace('-', '_')))
 
                             # don't need this for xfel-calibrate
                             del thisconf["inset"]