Write strings to a file while downloading new one simultaneous
You have a lot of interesting things going on in your code. There are many ways to solve your problem, here is an approach utilizing an ActionBlock. I used .NET Core 3.1 to build the sample, but ActionBlock is available in the System.Threading.Tasks.Dataflow NuGet Package if it isn't included in your framework by default.

1) Change your entry point from static void Main(string[] args to static async Task Main(string[] args async main has been available since C#7.1 (https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-7-1). If you can't use C#7.1 or greater, you can still do it with something like DoAsyncWork().GetAwaiter().GetResult()

2) List is not guaranteed to be thread safe and I noticed you add to your list outside your lock. I elected to use a ConcurrentDictionary instead since that is guaranteed thread safe. I try to avoid my own locks whenever I can and in this case, if you get rid of the Console writes, you could dump your lock altogether.

3) I elected to use Interlocked.Increment(ref requestDid) instead of {requestDid++} and then read it with an Interlocked.Read. Interlocked operations are thread safe, so you would be okay to use these even if you removed lock (ConsoleLock) (although you are only using those variables to write to the Console anyway)

4) In an async/await world, Thread.Sleep is almost always wrong. You usually want to await Task.Delay instead. https://stackoverflow.com/questions/20082221/when-to-use-task-delay-when-to-use-thread-sleep

5) I didn't Dispose the httpclient or handler because of https://stackoverflow.com/questions/15705092/do-httpclient-and-httpclienthandler-have-to-be-disposed (although since the program is terminating anyway, it doesn't really matter in this case)

6) As far as the ActionBlock goes, there are a lot of articles out there on it, but here is an ok start https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/dataflow-task-parallel-library. Note how I set EnsureOrdered to false. If you don't need the items to be processed in order, I find it best to set it to false. In this case, since you are writing the file after you have retrieved ALL the results, you could simply sort the values coming out of the ConcurrentDictionary

I set SingleProducerConstrained to true, because in this case post is not being called concurrently. This allows the ActionBlock to make some optimizations. https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.dataflow.executiondataflowblockoptions.singleproducerconstrained?view=netcore-3.1

MaxDegreesOfParallelism can be a tough choice. I sometimes cringe when I see a hardcode for that in real world applications because the optimal value for this will likely vary based on what hardware or virtualization platform you are running on. However, the optimal value can be hard to come by, especially when running a container. This is a great example of how nuanced the choice can be. https://github.com/dotnet/runtime/issues/622

7) Finally, I have found when testing performance like this, to make sure you do so WITHOUT a debugger attached. Attached debuggers can really slow things down. I built this code in release mode and then ran it from the command line.

using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;

namespace RequestTest
{
    static class Program
    {
        static async Task Main(string[] args)
        {
            var startTime = Stopwatch.GetTimestamp();
            //DECLARATION           
            int start = 1000;
            int end = 2000;
            long requestDid = 0;
            var requestToDo = end - start;

            object ConsoleLock = new object();
            ConcurrentDictionary&lt;string, string&gt; jsonResponses = new ConcurrentDictionary&lt;string, string&gt;();
            var baseAddress = new Uri("https://localhost:5001/");
            var cookieContainer = new CookieContainer();
            cookieContainer.Add(baseAddress, new Cookie("JSESSIONID", "xxx"));
            var handler = new HttpClientHandler() { CookieContainer = cookieContainer };
            var client = new HttpClient(handler) { BaseAddress = baseAddress };
            var actionBlock = new ActionBlock&lt;string&gt;(async x =&gt;
            {
                var response = await client.GetStringAsync(new Uri(baseAddress + x));
                jsonResponses.TryAdd(x, response); //note this actually returns a bool to indictate if it was added successfully, as long as x is unqiue, I can't imagine a scenario where this would return false
                lock (ConsoleLock)
                {
                    Console.SetCursorPosition(0, 0);
                    Interlocked.Increment(ref requestDid);
                    Console.Write($"Progress {Interlocked.Read(ref requestDid)}/{requestToDo}     ");
                }

            }, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 8, EnsureOrdered = false, SingleProducerConstrained = true }); 

            for (var counter = start; counter&lt;end; counter++)
            {
                actionBlock.Post("api/test?requestid="+counter.ToString());
            }
            actionBlock.Complete();
            await actionBlock.Completion;
            var endRequestTime = Stopwatch.GetTimestamp();
            Console.WriteLine();
            Console.WriteLine();
            Console.WriteLine();
            Console.WriteLine();
            Console.WriteLine($"Executed Requests in {(endRequestTime - startTime)} ticks");
            Console.WriteLine("Writing to file");

            using (var streamWriter = new StreamWriter("C:\\temp\\sctest.txt"))
            {
                foreach (var sc in jsonResponses.Values)
                {
                    streamWriter.WriteLine(sc);
                }
            }

            var endFileTime = Stopwatch.GetTimestamp();
            Console.WriteLine($"Completed File write in {(endFileTime - endRequestTime)} ticks");
        }
    }
}


```